blob: 99aa6fb6f465b5c3f3b0530b0e36e75fe3bf6057 [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 Calderone8322d782010-09-17 19:22:31 -04008from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK
Jean-Paul Calderone52f0d8b2009-03-07 09:10:19 -05009from sys import platform
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -040010from socket import error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040011from os import makedirs
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -040012from os.path import join
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040013from unittest import main
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050014
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040015from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM, FILETYPE_ASN1
16from OpenSSL.crypto import PKey, X509, X509Extension
17from OpenSSL.crypto import dump_privatekey, load_privatekey
18from OpenSSL.crypto import dump_certificate, load_certificate
19
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040020from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
21from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040022from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040023from OpenSSL.SSL import SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD
Jean-Paul Calderone68649052009-07-17 21:14:27 -040024from OpenSSL.SSL import OP_NO_SSLv2, OP_NO_SSLv3, OP_SINGLE_DH_USE
Rick Deanb71c0d22009-04-01 14:09:23 -050025from OpenSSL.SSL import VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040026from OpenSSL.SSL import Error, SysCallError, WantReadError, ZeroReturnError, SSLeay_version
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040027from OpenSSL.SSL import Context, ContextType, Connection, ConnectionType
28
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -040029from OpenSSL.test.util import TestCase, bytes, b
Jean-Paul Calderone18808652009-07-05 12:54:05 -040030from OpenSSL.test.test_crypto import cleartextCertificatePEM, cleartextPrivateKeyPEM
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040031from OpenSSL.test.test_crypto import client_cert_pem, client_key_pem
32from OpenSSL.test.test_crypto import server_cert_pem, server_key_pem, root_cert_pem
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050033try:
34 from OpenSSL.SSL import OP_NO_QUERY_MTU
35except ImportError:
36 OP_NO_QUERY_MTU = None
37try:
38 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
39except ImportError:
40 OP_COOKIE_EXCHANGE = None
41try:
42 from OpenSSL.SSL import OP_NO_TICKET
43except ImportError:
44 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040045
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040046from OpenSSL.SSL import (
47 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
48 SSL_ST_OK, SSL_ST_RENEGOTIATE,
49 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
50 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
51 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
52 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040053
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040054# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
55# to use)
56dhparam = """\
57-----BEGIN DH PARAMETERS-----
58MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
59-----END DH PARAMETERS-----
60"""
61
62
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040063def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040064 return ok
65
Rick Deanb1ccd562009-07-09 23:52:39 -050066def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040067 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -040068 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040069 """
70 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -050071 port = socket()
72 port.bind(('', 0))
73 port.listen(1)
74 client = socket()
75 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -040076 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040077 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -050078 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -050079
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040080 # Let's pass some unencrypted data to make sure our socket connection is
81 # fine. Just one byte, so we don't have to worry about buffers getting
82 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -040083 server.send(b("x"))
84 assert client.recv(1024) == b("x")
85 client.send(b("y"))
86 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -050087
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -040088 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040089 server.setblocking(False)
90 client.setblocking(False)
91
Rick Deanb1ccd562009-07-09 23:52:39 -050092 return (server, client)
93
94
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040095
Jean-Paul Calderonef8742032010-09-25 00:00:32 -040096def handshake(client, server):
97 conns = [client, server]
98 while conns:
99 for conn in conns:
100 try:
101 conn.do_handshake()
102 except WantReadError:
103 pass
104 else:
105 conns.remove(conn)
106
107
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400108class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400109 """
110 Helper mixin which defines methods for creating a connected socket pair and
111 for forcing two connected SSL sockets to talk to each other via memory BIOs.
112 """
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400113 def _loopback(self):
114 (server, client) = socket_pair()
115
116 ctx = Context(TLSv1_METHOD)
117 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
118 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
119 server = Connection(ctx, server)
120 server.set_accept_state()
121 client = Connection(Context(TLSv1_METHOD), client)
122 client.set_connect_state()
123
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400124 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400125
126 server.setblocking(True)
127 client.setblocking(True)
128 return server, client
129
130
131 def _interactInMemory(self, client_conn, server_conn):
132 """
133 Try to read application bytes from each of the two L{Connection}
134 objects. Copy bytes back and forth between their send/receive buffers
135 for as long as there is anything to copy. When there is nothing more
136 to copy, return C{None}. If one of them actually manages to deliver
137 some application bytes, return a two-tuple of the connection from which
138 the bytes were read and the bytes themselves.
139 """
140 wrote = True
141 while wrote:
142 # Loop until neither side has anything to say
143 wrote = False
144
145 # Copy stuff from each side's send buffer to the other side's
146 # receive buffer.
147 for (read, write) in [(client_conn, server_conn),
148 (server_conn, client_conn)]:
149
150 # Give the side a chance to generate some more bytes, or
151 # succeed.
152 try:
153 bytes = read.recv(2 ** 16)
154 except WantReadError:
155 # It didn't succeed, so we'll hope it generated some
156 # output.
157 pass
158 else:
159 # It did succeed, so we'll stop now and let the caller deal
160 # with it.
161 return (read, bytes)
162
163 while True:
164 # Keep copying as long as there's more stuff there.
165 try:
166 dirty = read.bio_read(4096)
167 except WantReadError:
168 # Okay, nothing more waiting to be sent. Stop
169 # processing this send buffer.
170 break
171 else:
172 # Keep track of the fact that someone generated some
173 # output.
174 wrote = True
175 write.bio_write(dirty)
176
177
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400178class VersionTests(TestCase):
179 """
180 Tests for version information exposed by
181 L{OpenSSL.SSL.SSLeay_version} and
182 L{OpenSSL.SSL.OPENSSL_VERSION_NUMBER}.
183 """
184 def test_OPENSSL_VERSION_NUMBER(self):
185 """
186 L{OPENSSL_VERSION_NUMBER} is an integer with status in the low
187 byte and the patch, fix, minor, and major versions in the
188 nibbles above that.
189 """
190 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
191
192
193 def test_SSLeay_version(self):
194 """
195 L{SSLeay_version} takes a version type indicator and returns
196 one of a number of version strings based on that indicator.
197 """
198 versions = {}
199 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
200 SSLEAY_PLATFORM, SSLEAY_DIR]:
201 version = SSLeay_version(t)
202 versions[version] = t
203 self.assertTrue(isinstance(version, bytes))
204 self.assertEqual(len(versions), 5)
205
206
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400207
208class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400209 """
210 Unit tests for L{OpenSSL.SSL.Context}.
211 """
212 def test_method(self):
213 """
214 L{Context} can be instantiated with one of L{SSLv2_METHOD},
215 L{SSLv3_METHOD}, L{SSLv23_METHOD}, or L{TLSv1_METHOD}.
216 """
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400217 for meth in [SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400218 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400219
220 try:
221 Context(SSLv2_METHOD)
222 except ValueError:
223 # Some versions of OpenSSL have SSLv2, some don't.
224 # Difficult to say in advance.
225 pass
226
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400227 self.assertRaises(TypeError, Context, "")
228 self.assertRaises(ValueError, Context, 10)
229
230
Rick Deane15b1472009-07-09 15:53:42 -0500231 def test_type(self):
232 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400233 L{Context} and L{ContextType} refer to the same type object and can be
234 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500235 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400236 self.assertIdentical(Context, ContextType)
237 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500238
239
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400240 def test_use_privatekey(self):
241 """
242 L{Context.use_privatekey} takes an L{OpenSSL.crypto.PKey} instance.
243 """
244 key = PKey()
245 key.generate_key(TYPE_RSA, 128)
246 ctx = Context(TLSv1_METHOD)
247 ctx.use_privatekey(key)
248 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400249
250
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400251 def test_set_app_data_wrong_args(self):
252 """
253 L{Context.set_app_data} raises L{TypeError} if called with other than
254 one argument.
255 """
256 context = Context(TLSv1_METHOD)
257 self.assertRaises(TypeError, context.set_app_data)
258 self.assertRaises(TypeError, context.set_app_data, None, None)
259
260
261 def test_get_app_data_wrong_args(self):
262 """
263 L{Context.get_app_data} raises L{TypeError} if called with any
264 arguments.
265 """
266 context = Context(TLSv1_METHOD)
267 self.assertRaises(TypeError, context.get_app_data, None)
268
269
270 def test_app_data(self):
271 """
272 L{Context.set_app_data} stores an object for later retrieval using
273 L{Context.get_app_data}.
274 """
275 app_data = object()
276 context = Context(TLSv1_METHOD)
277 context.set_app_data(app_data)
278 self.assertIdentical(context.get_app_data(), app_data)
279
280
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400281 def test_set_options_wrong_args(self):
282 """
283 L{Context.set_options} raises L{TypeError} if called with the wrong
284 number of arguments or a non-C{int} argument.
285 """
286 context = Context(TLSv1_METHOD)
287 self.assertRaises(TypeError, context.set_options)
288 self.assertRaises(TypeError, context.set_options, None)
289 self.assertRaises(TypeError, context.set_options, 1, None)
290
291
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400292 def test_set_timeout_wrong_args(self):
293 """
294 L{Context.set_timeout} raises L{TypeError} if called with the wrong
295 number of arguments or a non-C{int} argument.
296 """
297 context = Context(TLSv1_METHOD)
298 self.assertRaises(TypeError, context.set_timeout)
299 self.assertRaises(TypeError, context.set_timeout, None)
300 self.assertRaises(TypeError, context.set_timeout, 1, None)
301
302
303 def test_get_timeout_wrong_args(self):
304 """
305 L{Context.get_timeout} raises L{TypeError} if called with any arguments.
306 """
307 context = Context(TLSv1_METHOD)
308 self.assertRaises(TypeError, context.get_timeout, None)
309
310
311 def test_timeout(self):
312 """
313 L{Context.set_timeout} sets the session timeout for all connections
314 created using the context object. L{Context.get_timeout} retrieves this
315 value.
316 """
317 context = Context(TLSv1_METHOD)
318 context.set_timeout(1234)
319 self.assertEquals(context.get_timeout(), 1234)
320
321
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400322 def test_set_verify_depth_wrong_args(self):
323 """
324 L{Context.set_verify_depth} raises L{TypeError} if called with the wrong
325 number of arguments or a non-C{int} argument.
326 """
327 context = Context(TLSv1_METHOD)
328 self.assertRaises(TypeError, context.set_verify_depth)
329 self.assertRaises(TypeError, context.set_verify_depth, None)
330 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
331
332
333 def test_get_verify_depth_wrong_args(self):
334 """
335 L{Context.get_verify_depth} raises L{TypeError} if called with any arguments.
336 """
337 context = Context(TLSv1_METHOD)
338 self.assertRaises(TypeError, context.get_verify_depth, None)
339
340
341 def test_verify_depth(self):
342 """
343 L{Context.set_verify_depth} sets the number of certificates in a chain
344 to follow before giving up. The value can be retrieved with
345 L{Context.get_verify_depth}.
346 """
347 context = Context(TLSv1_METHOD)
348 context.set_verify_depth(11)
349 self.assertEquals(context.get_verify_depth(), 11)
350
351
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400352 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400353 """
354 Write a new private key out to a new file, encrypted using the given
355 passphrase. Return the path to the new file.
356 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400357 key = PKey()
358 key.generate_key(TYPE_RSA, 128)
359 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400360 fObj = open(pemFile, 'w')
361 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
362 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400363 fObj.close()
364 return pemFile
365
366
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400367 def test_set_passwd_cb_wrong_args(self):
368 """
369 L{Context.set_passwd_cb} raises L{TypeError} if called with the
370 wrong arguments or with a non-callable first argument.
371 """
372 context = Context(TLSv1_METHOD)
373 self.assertRaises(TypeError, context.set_passwd_cb)
374 self.assertRaises(TypeError, context.set_passwd_cb, None)
375 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
376
377
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400378 def test_set_passwd_cb(self):
379 """
380 L{Context.set_passwd_cb} accepts a callable which will be invoked when
381 a private key is loaded from an encrypted PEM.
382 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400383 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400384 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400385 calledWith = []
386 def passphraseCallback(maxlen, verify, extra):
387 calledWith.append((maxlen, verify, extra))
388 return passphrase
389 context = Context(TLSv1_METHOD)
390 context.set_passwd_cb(passphraseCallback)
391 context.use_privatekey_file(pemFile)
392 self.assertTrue(len(calledWith), 1)
393 self.assertTrue(isinstance(calledWith[0][0], int))
394 self.assertTrue(isinstance(calledWith[0][1], int))
395 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400396
397
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400398 def test_passwd_callback_exception(self):
399 """
400 L{Context.use_privatekey_file} propagates any exception raised by the
401 passphrase callback.
402 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400403 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400404 def passphraseCallback(maxlen, verify, extra):
405 raise RuntimeError("Sorry, I am a fail.")
406
407 context = Context(TLSv1_METHOD)
408 context.set_passwd_cb(passphraseCallback)
409 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
410
411
412 def test_passwd_callback_false(self):
413 """
414 L{Context.use_privatekey_file} raises L{OpenSSL.SSL.Error} if the
415 passphrase callback returns a false value.
416 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400417 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400418 def passphraseCallback(maxlen, verify, extra):
419 return None
420
421 context = Context(TLSv1_METHOD)
422 context.set_passwd_cb(passphraseCallback)
423 self.assertRaises(Error, context.use_privatekey_file, pemFile)
424
425
426 def test_passwd_callback_non_string(self):
427 """
428 L{Context.use_privatekey_file} raises L{OpenSSL.SSL.Error} if the
429 passphrase callback returns a true non-string value.
430 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400431 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400432 def passphraseCallback(maxlen, verify, extra):
433 return 10
434
435 context = Context(TLSv1_METHOD)
436 context.set_passwd_cb(passphraseCallback)
437 self.assertRaises(Error, context.use_privatekey_file, pemFile)
438
439
440 def test_passwd_callback_too_long(self):
441 """
442 If the passphrase returned by the passphrase callback returns a string
443 longer than the indicated maximum length, it is truncated.
444 """
445 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400446 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400447 pemFile = self._write_encrypted_pem(passphrase)
448 def passphraseCallback(maxlen, verify, extra):
449 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400450 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400451
452 context = Context(TLSv1_METHOD)
453 context.set_passwd_cb(passphraseCallback)
454 # This shall succeed because the truncated result is the correct
455 # passphrase.
456 context.use_privatekey_file(pemFile)
457
458
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400459 def test_set_info_callback(self):
460 """
461 L{Context.set_info_callback} accepts a callable which will be invoked
462 when certain information about an SSL connection is available.
463 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500464 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400465
466 clientSSL = Connection(Context(TLSv1_METHOD), client)
467 clientSSL.set_connect_state()
468
469 called = []
470 def info(conn, where, ret):
471 called.append((conn, where, ret))
472 context = Context(TLSv1_METHOD)
473 context.set_info_callback(info)
474 context.use_certificate(
475 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
476 context.use_privatekey(
477 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
478
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400479 serverSSL = Connection(context, server)
480 serverSSL.set_accept_state()
481
482 while not called:
483 for ssl in clientSSL, serverSSL:
484 try:
485 ssl.do_handshake()
486 except WantReadError:
487 pass
488
489 # Kind of lame. Just make sure it got called somehow.
490 self.assertTrue(called)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400491
492
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400493 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400494 """
495 Create a client context which will verify the peer certificate and call
496 its C{load_verify_locations} method with C{*args}. Then connect it to a
497 server and ensure that the handshake succeeds.
498 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500499 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400500
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400501 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400502 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400503 # Require that the server certificate verify properly or the
504 # connection will fail.
505 clientContext.set_verify(
506 VERIFY_PEER,
507 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
508
509 clientSSL = Connection(clientContext, client)
510 clientSSL.set_connect_state()
511
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400512 serverContext = Context(TLSv1_METHOD)
513 serverContext.use_certificate(
514 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
515 serverContext.use_privatekey(
516 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
517
518 serverSSL = Connection(serverContext, server)
519 serverSSL.set_accept_state()
520
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400521 # Without load_verify_locations above, the handshake
522 # will fail:
523 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
524 # 'certificate verify failed')]
525 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400526
527 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400528 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400529
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500530
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400531 def test_load_verify_file(self):
532 """
533 L{Context.load_verify_locations} accepts a file name and uses the
534 certificates within for verification purposes.
535 """
536 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400537 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400538 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400539 fObj.close()
540
541 self._load_verify_locations_test(cafile)
542
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400543
544 def test_load_verify_invalid_file(self):
545 """
546 L{Context.load_verify_locations} raises L{Error} when passed a
547 non-existent cafile.
548 """
549 clientContext = Context(TLSv1_METHOD)
550 self.assertRaises(
551 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400552
553
554 def test_load_verify_directory(self):
555 """
556 L{Context.load_verify_locations} accepts a directory name and uses
557 the certificates within for verification purposes.
558 """
559 capath = self.mktemp()
560 makedirs(capath)
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -0400561 # Hash value computed manually with c_rehash to avoid depending on
562 # c_rehash in the test suite.
563 cafile = join(capath, 'c7adac82.0')
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400564 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400565 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400566 fObj.close()
567
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400568 self._load_verify_locations_test(None, capath)
569
570
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400571 def test_load_verify_locations_wrong_args(self):
572 """
573 L{Context.load_verify_locations} raises L{TypeError} if called with
574 the wrong number of arguments or with non-C{str} arguments.
575 """
576 context = Context(TLSv1_METHOD)
577 self.assertRaises(TypeError, context.load_verify_locations)
578 self.assertRaises(TypeError, context.load_verify_locations, object())
579 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
580 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
581
582
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400583 if platform == "win32":
584 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400585 "See LP#404343 and LP#404344."
586 else:
587 def test_set_default_verify_paths(self):
588 """
589 L{Context.set_default_verify_paths} causes the platform-specific CA
590 certificate locations to be used for verification purposes.
591 """
592 # Testing this requires a server with a certificate signed by one of
593 # the CAs in the platform CA location. Getting one of those costs
594 # money. Fortunately (or unfortunately, depending on your
595 # perspective), it's easy to think of a public server on the
596 # internet which has such a certificate. Connecting to the network
597 # in a unit test is bad, but it's the only way I can think of to
598 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400599
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400600 # Arg, verisign.com doesn't speak TLSv1
601 context = Context(SSLv3_METHOD)
602 context.set_default_verify_paths()
603 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200604 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400605 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400606
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400607 client = socket()
608 client.connect(('verisign.com', 443))
609 clientSSL = Connection(context, client)
610 clientSSL.set_connect_state()
611 clientSSL.do_handshake()
612 clientSSL.send('GET / HTTP/1.0\r\n\r\n')
613 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400614
615
616 def test_set_default_verify_paths_signature(self):
617 """
618 L{Context.set_default_verify_paths} takes no arguments and raises
619 L{TypeError} if given any.
620 """
621 context = Context(TLSv1_METHOD)
622 self.assertRaises(TypeError, context.set_default_verify_paths, None)
623 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
624 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500625
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400626
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500627 def test_add_extra_chain_cert_invalid_cert(self):
628 """
629 L{Context.add_extra_chain_cert} raises L{TypeError} if called with
630 other than one argument or if called with an object which is not an
631 instance of L{X509}.
632 """
633 context = Context(TLSv1_METHOD)
634 self.assertRaises(TypeError, context.add_extra_chain_cert)
635 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
636 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
637
638
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400639 def _create_certificate_chain(self):
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500640 """
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400641 Construct and return a chain of certificates.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400642
643 1. A new self-signed certificate authority certificate (cacert)
644 2. A new intermediate certificate signed by cacert (icert)
645 3. A new server certificate signed by icert (scert)
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500646 """
Jean-Paul Calderone9b0744c2010-09-14 18:11:01 -0400647 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500648
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400649 # Step 1
650 cakey = PKey()
651 cakey.generate_key(TYPE_RSA, 512)
652 cacert = X509()
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400653 cacert.get_subject().commonName = "Authority Certificate"
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400654 cacert.set_issuer(cacert.get_subject())
655 cacert.set_pubkey(cakey)
Jean-Paul Calderone4e6aed62010-09-19 10:05:34 -0400656 cacert.set_notBefore(b("20000101000000Z"))
657 cacert.set_notAfter(b("20200101000000Z"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400658 cacert.add_extensions([caext])
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400659 cacert.set_serial_number(0)
660 cacert.sign(cakey, "sha1")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500661
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400662 # Step 2
663 ikey = PKey()
664 ikey.generate_key(TYPE_RSA, 512)
665 icert = X509()
666 icert.get_subject().commonName = "Intermediate Certificate"
667 icert.set_issuer(cacert.get_subject())
668 icert.set_pubkey(ikey)
Jean-Paul Calderone4e6aed62010-09-19 10:05:34 -0400669 icert.set_notBefore(b("20000101000000Z"))
670 icert.set_notAfter(b("20200101000000Z"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400671 icert.add_extensions([caext])
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400672 icert.set_serial_number(0)
673 icert.sign(cakey, "sha1")
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400674
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400675 # Step 3
676 skey = PKey()
677 skey.generate_key(TYPE_RSA, 512)
678 scert = X509()
679 scert.get_subject().commonName = "Server Certificate"
680 scert.set_issuer(icert.get_subject())
681 scert.set_pubkey(skey)
Jean-Paul Calderone4e6aed62010-09-19 10:05:34 -0400682 scert.set_notBefore(b("20000101000000Z"))
683 scert.set_notAfter(b("20200101000000Z"))
Jean-Paul Calderone2db1de52010-09-19 10:08:13 -0400684 scert.add_extensions([
685 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400686 scert.set_serial_number(0)
687 scert.sign(ikey, "sha1")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400688
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400689 return [(cakey, cacert), (ikey, icert), (skey, scert)]
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400690
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400691
692 def _handshake_test(self, serverContext, clientContext):
693 """
694 Verify that a client and server created with the given contexts can
695 successfully handshake and communicate.
696 """
697 serverSocket, clientSocket = socket_pair()
698
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400699 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400700 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400701
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400702 client = Connection(clientContext, clientSocket)
703 client.set_connect_state()
704
705 # Make them talk to each other.
706 # self._interactInMemory(client, server)
707 for i in range(3):
708 for s in [client, server]:
709 try:
710 s.do_handshake()
711 except WantReadError:
712 pass
713
714
715 def test_add_extra_chain_cert(self):
716 """
717 L{Context.add_extra_chain_cert} accepts an L{X509} instance to add to
718 the certificate chain.
719
720 See L{_create_certificate_chain} for the details of the certificate
721 chain tested.
722
723 The chain is tested by starting a server with scert and connecting
724 to it with a client which trusts cacert and requires verification to
725 succeed.
726 """
727 chain = self._create_certificate_chain()
728 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
729
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400730 # Dump the CA certificate to a file because that's the only way to load
731 # it as a trusted CA in the client context.
732 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400733 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400734 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400735 fObj.close()
736
737 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400738 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400739 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400740 fObj.close()
741
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400742 # Create the server context
743 serverContext = Context(TLSv1_METHOD)
744 serverContext.use_privatekey(skey)
745 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400746 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400747 serverContext.add_extra_chain_cert(icert)
748
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400749 # Create the client
750 clientContext = Context(TLSv1_METHOD)
751 clientContext.set_verify(
752 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
753 clientContext.load_verify_locations('ca.pem')
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400754
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400755 # Try it out.
756 self._handshake_test(serverContext, clientContext)
757
758
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400759 def test_use_certificate_chain_file(self):
760 """
761 L{Context.use_certificate_chain_file} reads a certificate chain from
762 the specified file.
763
764 The chain is tested by starting a server with scert and connecting
765 to it with a client which trusts cacert and requires verification to
766 succeed.
767 """
768 chain = self._create_certificate_chain()
769 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
770
771 # Write out the chain file.
772 chainFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400773 fObj = open(chainFile, 'w')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400774 # Most specific to least general.
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400775 fObj.write(dump_certificate(FILETYPE_PEM, scert).decode('ascii'))
776 fObj.write(dump_certificate(FILETYPE_PEM, icert).decode('ascii'))
777 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400778 fObj.close()
779
780 serverContext = Context(TLSv1_METHOD)
781 serverContext.use_certificate_chain_file(chainFile)
782 serverContext.use_privatekey(skey)
783
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400784 fObj = open('ca.pem', 'w')
785 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400786 fObj.close()
787
788 clientContext = Context(TLSv1_METHOD)
789 clientContext.set_verify(
790 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
791 clientContext.load_verify_locations('ca.pem')
792
793 self._handshake_test(serverContext, clientContext)
794
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -0400795 # XXX load_client_ca
796 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -0400797
798 def test_get_verify_mode_wrong_args(self):
799 """
800 L{Context.get_verify_mode} raises L{TypeError} if called with any
801 arguments.
802 """
803 context = Context(TLSv1_METHOD)
804 self.assertRaises(TypeError, context.get_verify_mode, None)
805
806
807 def test_get_verify_mode(self):
808 """
809 L{Context.get_verify_mode} returns the verify mode flags previously
810 passed to L{Context.set_verify}.
811 """
812 context = Context(TLSv1_METHOD)
813 self.assertEquals(context.get_verify_mode(), 0)
814 context.set_verify(
815 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
816 self.assertEquals(
817 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
818
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400819
820 def test_load_tmp_dh_wrong_args(self):
821 """
822 L{Context.load_tmp_dh} raises L{TypeError} if called with the wrong
823 number of arguments or with a non-C{str} argument.
824 """
825 context = Context(TLSv1_METHOD)
826 self.assertRaises(TypeError, context.load_tmp_dh)
827 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
828 self.assertRaises(TypeError, context.load_tmp_dh, object())
829
830
831 def test_load_tmp_dh_missing_file(self):
832 """
833 L{Context.load_tmp_dh} raises L{OpenSSL.SSL.Error} if the specified file
834 does not exist.
835 """
836 context = Context(TLSv1_METHOD)
837 self.assertRaises(Error, context.load_tmp_dh, "hello")
838
839
840 def test_load_tmp_dh(self):
841 """
842 L{Context.load_tmp_dh} loads Diffie-Hellman parameters from the
843 specified file.
844 """
845 context = Context(TLSv1_METHOD)
846 dhfilename = self.mktemp()
847 dhfile = open(dhfilename, "w")
848 dhfile.write(dhparam)
849 dhfile.close()
850 context.load_tmp_dh(dhfilename)
851 # XXX What should I assert here? -exarkun
852
853
854 def test_set_cipher_list(self):
855 """
856 L{Context.set_cipher_list} accepts a C{str} naming the ciphers which
857 connections created with the context object will be able to choose from.
858 """
859 context = Context(TLSv1_METHOD)
860 context.set_cipher_list("hello world:EXP-RC4-MD5")
861 conn = Connection(context, None)
862 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400863
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400864
865
866class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -0500867 """
868 Unit tests for L{OpenSSL.SSL.Connection}.
869 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -0400870 # XXX want_write
871 # XXX want_read
872 # XXX get_peer_certificate -> None
873 # XXX sock_shutdown
874 # XXX master_key -> TypeError
875 # XXX server_random -> TypeError
876 # XXX state_string
877 # XXX connect -> TypeError
878 # XXX connect_ex -> TypeError
879 # XXX set_connect_state -> TypeError
880 # XXX set_accept_state -> TypeError
881 # XXX renegotiate_pending
882 # XXX do_handshake -> TypeError
883 # XXX bio_read -> TypeError
884 # XXX recv -> TypeError
885 # XXX send -> TypeError
886 # XXX bio_write -> TypeError
887
Rick Deane15b1472009-07-09 15:53:42 -0500888 def test_type(self):
889 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400890 L{Connection} and L{ConnectionType} refer to the same type object and
891 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500892 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400893 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -0500894 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400895 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -0500896
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400897
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -0500898 def test_get_context(self):
899 """
900 L{Connection.get_context} returns the L{Context} instance used to
901 construct the L{Connection} instance.
902 """
903 context = Context(TLSv1_METHOD)
904 connection = Connection(context, None)
905 self.assertIdentical(connection.get_context(), context)
906
907
908 def test_get_context_wrong_args(self):
909 """
910 L{Connection.get_context} raises L{TypeError} if called with any
911 arguments.
912 """
913 connection = Connection(Context(TLSv1_METHOD), None)
914 self.assertRaises(TypeError, connection.get_context, None)
915
916
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -0400917 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400918 """
919 L{Connection.pending} returns the number of bytes available for
920 immediate read.
921 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -0400922 connection = Connection(Context(TLSv1_METHOD), None)
923 self.assertEquals(connection.pending(), 0)
924
925
926 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400927 """
928 L{Connection.pending} raises L{TypeError} if called with any arguments.
929 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -0400930 connection = Connection(Context(TLSv1_METHOD), None)
931 self.assertRaises(TypeError, connection.pending, None)
932
933
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400934 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400935 """
936 L{Connection.connect} raises L{TypeError} if called with a non-address
937 argument or with the wrong number of arguments.
938 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400939 connection = Connection(Context(TLSv1_METHOD), socket())
940 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400941 self.assertRaises(TypeError, connection.connect)
942 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400943
944
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400945 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400946 """
947 L{Connection.connect} raises L{socket.error} if the underlying socket
948 connect method raises it.
949 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400950 client = socket()
951 context = Context(TLSv1_METHOD)
952 clientSSL = Connection(context, client)
953 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -0400954 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400955
956
957 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400958 """
959 L{Connection.connect} establishes a connection to the specified address.
960 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400961 port = socket()
962 port.bind(('', 0))
963 port.listen(3)
964
965 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -0400966 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
967 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400968
969
Jean-Paul Calderone7b614872010-09-24 17:43:44 -0400970 if platform == "darwin":
971 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
972 else:
973 def test_connect_ex(self):
974 """
975 If there is a connection error, L{Connection.connect_ex} returns the
976 errno instead of raising an exception.
977 """
978 port = socket()
979 port.bind(('', 0))
980 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -0400981
Jean-Paul Calderone7b614872010-09-24 17:43:44 -0400982 clientSSL = Connection(Context(TLSv1_METHOD), socket())
983 clientSSL.setblocking(False)
984 result = clientSSL.connect_ex(port.getsockname())
985 expected = (EINPROGRESS, EWOULDBLOCK)
986 self.assertTrue(
987 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -0400988
989
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400990 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400991 """
992 L{Connection.accept} raises L{TypeError} if called with any arguments.
993 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400994 connection = Connection(Context(TLSv1_METHOD), socket())
995 self.assertRaises(TypeError, connection.accept, None)
996
997
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400998 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400999 """
1000 L{Connection.accept} accepts a pending connection attempt and returns a
1001 tuple of a new L{Connection} (the accepted client) and the address the
1002 connection originated from.
1003 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001004 ctx = Context(TLSv1_METHOD)
1005 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1006 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001007 port = socket()
1008 portSSL = Connection(ctx, port)
1009 portSSL.bind(('', 0))
1010 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001011
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001012 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001013
1014 # Calling portSSL.getsockname() here to get the server IP address sounds
1015 # great, but frequently fails on Windows.
1016 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001017
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001018 serverSSL, address = portSSL.accept()
1019
1020 self.assertTrue(isinstance(serverSSL, Connection))
1021 self.assertIdentical(serverSSL.get_context(), ctx)
1022 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001023
1024
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001025 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001026 """
1027 L{Connection.shutdown} raises L{TypeError} if called with the wrong
1028 number of arguments or with arguments other than integers.
1029 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001030 connection = Connection(Context(TLSv1_METHOD), None)
1031 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001032 self.assertRaises(TypeError, connection.get_shutdown, None)
1033 self.assertRaises(TypeError, connection.set_shutdown)
1034 self.assertRaises(TypeError, connection.set_shutdown, None)
1035 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001036
1037
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001038 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001039 """
1040 L{Connection.shutdown} performs an SSL-level connection shutdown.
1041 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001042 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001043 self.assertFalse(server.shutdown())
1044 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001045 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001046 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1047 client.shutdown()
1048 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1049 self.assertRaises(ZeroReturnError, server.recv, 1024)
1050 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001051
1052
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001053 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001054 """
1055 L{Connection.set_shutdown} sets the state of the SSL connection shutdown
1056 process.
1057 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001058 connection = Connection(Context(TLSv1_METHOD), socket())
1059 connection.set_shutdown(RECEIVED_SHUTDOWN)
1060 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1061
1062
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001063 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001064 """
1065 L{Connection.set_app_data} raises L{TypeError} if called with other than
1066 one argument. L{Connection.get_app_data} raises L{TypeError} if called
1067 with any arguments.
1068 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001069 conn = Connection(Context(TLSv1_METHOD), None)
1070 self.assertRaises(TypeError, conn.get_app_data, None)
1071 self.assertRaises(TypeError, conn.set_app_data)
1072 self.assertRaises(TypeError, conn.set_app_data, None, None)
1073
1074
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001075 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001076 """
1077 Any object can be set as app data by passing it to
1078 L{Connection.set_app_data} and later retrieved with
1079 L{Connection.get_app_data}.
1080 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001081 conn = Connection(Context(TLSv1_METHOD), None)
1082 app_data = object()
1083 conn.set_app_data(app_data)
1084 self.assertIdentical(conn.get_app_data(), app_data)
1085
1086
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001087 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001088 """
1089 L{Connection.makefile} is not implemented and calling that method raises
1090 L{NotImplementedError}.
1091 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001092 conn = Connection(Context(TLSv1_METHOD), None)
1093 self.assertRaises(NotImplementedError, conn.makefile)
1094
1095
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001096
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001097class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001098 """
1099 Tests for L{Connection.get_cipher_list}.
1100 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04001101 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001102 """
1103 L{Connection.get_cipher_list} raises L{TypeError} if called with any
1104 arguments.
1105 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001106 connection = Connection(Context(TLSv1_METHOD), None)
1107 self.assertRaises(TypeError, connection.get_cipher_list, None)
1108
1109
1110 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001111 """
1112 L{Connection.get_cipher_list} returns a C{list} of C{str} giving the
1113 names of the ciphers which might be used.
1114 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001115 connection = Connection(Context(TLSv1_METHOD), None)
1116 ciphers = connection.get_cipher_list()
1117 self.assertTrue(isinstance(ciphers, list))
1118 for cipher in ciphers:
1119 self.assertTrue(isinstance(cipher, str))
1120
1121
1122
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001123class ConnectionSendTests(TestCase, _LoopbackMixin):
1124 """
1125 Tests for L{Connection.send}
1126 """
1127 def test_wrong_args(self):
1128 """
1129 When called with arguments other than a single string,
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05001130 L{Connection.send} raises L{TypeError}.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001131 """
1132 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05001133 self.assertRaises(TypeError, connection.send)
1134 self.assertRaises(TypeError, connection.send, object())
1135 self.assertRaises(TypeError, connection.send, "foo", "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001136
1137
1138 def test_short_bytes(self):
1139 """
1140 When passed a short byte string, L{Connection.send} transmits all of it
1141 and returns the number of bytes sent.
1142 """
1143 server, client = self._loopback()
1144 count = server.send(b('xy'))
1145 self.assertEquals(count, 2)
1146 self.assertEquals(client.recv(2), b('xy'))
1147
1148 try:
1149 memoryview
1150 except NameError:
1151 "cannot test sending memoryview without memoryview"
1152 else:
1153 def test_short_memoryview(self):
1154 """
1155 When passed a memoryview onto a small number of bytes,
1156 L{Connection.send} transmits all of them and returns the number of
1157 bytes sent.
1158 """
1159 server, client = self._loopback()
1160 count = server.send(memoryview(b('xy')))
1161 self.assertEquals(count, 2)
1162 self.assertEquals(client.recv(2), b('xy'))
1163
1164
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001165
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001166class ConnectionSendallTests(TestCase, _LoopbackMixin):
1167 """
1168 Tests for L{Connection.sendall}.
1169 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001170 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001171 """
1172 When called with arguments other than a single string,
1173 L{Connection.sendall} raises L{TypeError}.
1174 """
1175 connection = Connection(Context(TLSv1_METHOD), None)
1176 self.assertRaises(TypeError, connection.sendall)
1177 self.assertRaises(TypeError, connection.sendall, object())
1178 self.assertRaises(TypeError, connection.sendall, "foo", "bar")
1179
1180
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001181 def test_short(self):
1182 """
1183 L{Connection.sendall} transmits all of the bytes in the string passed to
1184 it.
1185 """
1186 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001187 server.sendall(b('x'))
1188 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001189
1190
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001191 try:
1192 memoryview
1193 except NameError:
1194 "cannot test sending memoryview without memoryview"
1195 else:
1196 def test_short_memoryview(self):
1197 """
1198 When passed a memoryview onto a small number of bytes,
1199 L{Connection.sendall} transmits all of them.
1200 """
1201 server, client = self._loopback()
1202 server.sendall(memoryview(b('x')))
1203 self.assertEquals(client.recv(1), b('x'))
1204
1205
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001206 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001207 """
1208 L{Connection.sendall} transmits all of the bytes in the string passed to
1209 it even if this requires multiple calls of an underlying write function.
1210 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001211 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04001212 # Should be enough, underlying SSL_write should only do 16k at a time.
1213 # On Windows, after 32k of bytes the write will block (forever - because
1214 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04001215 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001216 server.sendall(message)
1217 accum = []
1218 received = 0
1219 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001220 data = client.recv(1024)
1221 accum.append(data)
1222 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04001223 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001224
1225
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001226 def test_closed(self):
1227 """
1228 If the underlying socket is closed, L{Connection.sendall} propagates the
1229 write error from the low level write call.
1230 """
1231 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04001232 server.sock_shutdown(2)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001233 self.assertRaises(SysCallError, server.sendall, "hello, world")
1234
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001235
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001236
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001237class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
1238 """
1239 Tests for SSL renegotiation APIs.
1240 """
1241 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001242 """
1243 L{Connection.renegotiate} raises L{TypeError} if called with any
1244 arguments.
1245 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001246 connection = Connection(Context(TLSv1_METHOD), None)
1247 self.assertRaises(TypeError, connection.renegotiate, None)
1248
1249
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001250 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001251 """
1252 L{Connection.total_renegotiations} raises L{TypeError} if called with
1253 any arguments.
1254 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001255 connection = Connection(Context(TLSv1_METHOD), None)
1256 self.assertRaises(TypeError, connection.total_renegotiations, None)
1257
1258
1259 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001260 """
1261 L{Connection.total_renegotiations} returns C{0} before any
1262 renegotiations have happened.
1263 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001264 connection = Connection(Context(TLSv1_METHOD), None)
1265 self.assertEquals(connection.total_renegotiations(), 0)
1266
1267
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001268# def test_renegotiate(self):
1269# """
1270# """
1271# server, client = self._loopback()
1272
1273# server.send("hello world")
1274# self.assertEquals(client.recv(len("hello world")), "hello world")
1275
1276# self.assertEquals(server.total_renegotiations(), 0)
1277# self.assertTrue(server.renegotiate())
1278
1279# server.setblocking(False)
1280# client.setblocking(False)
1281# while server.renegotiate_pending():
1282# client.do_handshake()
1283# server.do_handshake()
1284
1285# self.assertEquals(server.total_renegotiations(), 1)
1286
1287
1288
1289
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001290class ErrorTests(TestCase):
1291 """
1292 Unit tests for L{OpenSSL.SSL.Error}.
1293 """
1294 def test_type(self):
1295 """
1296 L{Error} is an exception type.
1297 """
1298 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05001299 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05001300
1301
1302
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001303class ConstantsTests(TestCase):
1304 """
1305 Tests for the values of constants exposed in L{OpenSSL.SSL}.
1306
1307 These are values defined by OpenSSL intended only to be used as flags to
1308 OpenSSL APIs. The only assertions it seems can be made about them is
1309 their values.
1310 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001311 # unittest.TestCase has no skip mechanism
1312 if OP_NO_QUERY_MTU is not None:
1313 def test_op_no_query_mtu(self):
1314 """
1315 The value of L{OpenSSL.SSL.OP_NO_QUERY_MTU} is 0x1000, the value of
1316 I{SSL_OP_NO_QUERY_MTU} defined by I{openssl/ssl.h}.
1317 """
1318 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
1319 else:
1320 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001321
1322
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001323 if OP_COOKIE_EXCHANGE is not None:
1324 def test_op_cookie_exchange(self):
1325 """
1326 The value of L{OpenSSL.SSL.OP_COOKIE_EXCHANGE} is 0x2000, the value
1327 of I{SSL_OP_COOKIE_EXCHANGE} defined by I{openssl/ssl.h}.
1328 """
1329 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
1330 else:
1331 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001332
1333
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001334 if OP_NO_TICKET is not None:
1335 def test_op_no_ticket(self):
1336 """
1337 The value of L{OpenSSL.SSL.OP_NO_TICKET} is 0x4000, the value of
1338 I{SSL_OP_NO_TICKET} defined by I{openssl/ssl.h}.
1339 """
1340 self.assertEqual(OP_NO_TICKET, 0x4000)
1341 else:
1342 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05001343
1344
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04001345
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001346class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05001347 """
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001348 Tests for L{OpenSSL.SSL.Connection} using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05001349 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001350 def _server(self, sock):
1351 """
1352 Create a new server-side SSL L{Connection} object wrapped around
1353 C{sock}.
1354 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001355 # Create the server side Connection. This is mostly setup boilerplate
1356 # - use TLSv1, use a particular certificate, etc.
1357 server_ctx = Context(TLSv1_METHOD)
1358 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1359 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1360 server_store = server_ctx.get_cert_store()
1361 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1362 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1363 server_ctx.check_privatekey()
1364 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001365 # Here the Connection is actually created. If None is passed as the 2nd
1366 # parameter, it indicates a memory BIO should be created.
1367 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001368 server_conn.set_accept_state()
1369 return server_conn
1370
1371
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001372 def _client(self, sock):
1373 """
1374 Create a new client-side SSL L{Connection} object wrapped around
1375 C{sock}.
1376 """
1377 # Now create the client side Connection. Similar boilerplate to the
1378 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001379 client_ctx = Context(TLSv1_METHOD)
1380 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1381 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1382 client_store = client_ctx.get_cert_store()
1383 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
1384 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
1385 client_ctx.check_privatekey()
1386 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001387 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001388 client_conn.set_connect_state()
1389 return client_conn
1390
1391
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001392 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001393 """
1394 Two L{Connection}s which use memory BIOs can be manually connected by
1395 reading from the output of each and writing those bytes to the input of
1396 the other and in this way establish a connection and exchange
1397 application-level bytes with each other.
1398 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001399 server_conn = self._server(None)
1400 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001401
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001402 # There should be no key or nonces yet.
1403 self.assertIdentical(server_conn.master_key(), None)
1404 self.assertIdentical(server_conn.client_random(), None)
1405 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001406
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001407 # First, the handshake needs to happen. We'll deliver bytes back and
1408 # forth between the client and server until neither of them feels like
1409 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001410 self.assertIdentical(
1411 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001412
1413 # Now that the handshake is done, there should be a key and nonces.
1414 self.assertNotIdentical(server_conn.master_key(), None)
1415 self.assertNotIdentical(server_conn.client_random(), None)
1416 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04001417 self.assertEquals(server_conn.client_random(), client_conn.client_random())
1418 self.assertEquals(server_conn.server_random(), client_conn.server_random())
1419 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
1420 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001421
1422 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04001423 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05001424
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001425 server_conn.write(important_message)
1426 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001427 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001428 (client_conn, important_message))
1429
1430 client_conn.write(important_message[::-1])
1431 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001432 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001433 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05001434
1435
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001436 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05001437 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001438 Just like L{test_memoryConnect} but with an actual socket.
1439
1440 This is primarily to rule out the memory BIO code as the source of
1441 any problems encountered while passing data over a L{Connection} (if
1442 this test fails, there must be a problem outside the memory BIO
1443 code, as no memory BIO is involved here). Even though this isn't a
1444 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05001445 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04001446 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05001447
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04001448 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05001449 client_conn.send(important_message)
1450 msg = server_conn.recv(1024)
1451 self.assertEqual(msg, important_message)
1452
1453 # Again in the other direction, just for fun.
1454 important_message = important_message[::-1]
1455 server_conn.send(important_message)
1456 msg = client_conn.recv(1024)
1457 self.assertEqual(msg, important_message)
1458
1459
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04001460 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05001461 """
1462 Test that L{OpenSSL.SSL.bio_read} and L{OpenSSL.SSL.bio_write} don't
1463 work on L{OpenSSL.SSL.Connection}() that use sockets.
1464 """
1465 context = Context(SSLv3_METHOD)
1466 client = socket()
1467 clientSSL = Connection(context, client)
1468 self.assertRaises( TypeError, clientSSL.bio_read, 100)
1469 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04001470 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001471
1472
1473 def test_outgoingOverflow(self):
1474 """
1475 If more bytes than can be written to the memory BIO are passed to
1476 L{Connection.send} at once, the number of bytes which were written is
1477 returned and that many bytes from the beginning of the input can be
1478 read from the other end of the connection.
1479 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001480 server = self._server(None)
1481 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001482
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001483 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001484
1485 size = 2 ** 15
1486 sent = client.send("x" * size)
1487 # Sanity check. We're trying to test what happens when the entire
1488 # input can't be sent. If the entire input was sent, this test is
1489 # meaningless.
1490 self.assertTrue(sent < size)
1491
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001492 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001493 self.assertIdentical(receiver, server)
1494
1495 # We can rely on all of these bytes being received at once because
1496 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
1497 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001498
1499
1500 def test_shutdown(self):
1501 """
1502 L{Connection.bio_shutdown} signals the end of the data stream from
1503 which the L{Connection} reads.
1504 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001505 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001506 server.bio_shutdown()
1507 e = self.assertRaises(Error, server.recv, 1024)
1508 # We don't want WantReadError or ZeroReturnError or anything - it's a
1509 # handshake failure.
1510 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001511
1512
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001513 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001514 """
1515 Verify the return value of the C{get_client_ca_list} method for server and client connections.
1516
1517 @param func: A function which will be called with the server context
1518 before the client and server are connected to each other. This
1519 function should specify a list of CAs for the server to send to the
1520 client and return that same list. The list will be used to verify
1521 that C{get_client_ca_list} returns the proper value at various
1522 times.
1523 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001524 server = self._server(None)
1525 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001526 self.assertEqual(client.get_client_ca_list(), [])
1527 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001528 ctx = server.get_context()
1529 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001530 self.assertEqual(client.get_client_ca_list(), [])
1531 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001532 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001533 self.assertEqual(client.get_client_ca_list(), expected)
1534 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001535
1536
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001537 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001538 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001539 L{Context.set_client_ca_list} raises a L{TypeError} if called with a
1540 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001541 """
1542 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001543 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
1544 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
1545 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001546
1547
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001548 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001549 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001550 If passed an empty list, L{Context.set_client_ca_list} configures the
1551 context to send no CA names to the client and, on both the server and
1552 client sides, L{Connection.get_client_ca_list} returns an empty list
1553 after the connection is set up.
1554 """
1555 def no_ca(ctx):
1556 ctx.set_client_ca_list([])
1557 return []
1558 self._check_client_ca_list(no_ca)
1559
1560
1561 def test_set_one_ca_list(self):
1562 """
1563 If passed a list containing a single X509Name,
1564 L{Context.set_client_ca_list} configures the context to send that CA
1565 name to the client and, on both the server and client sides,
1566 L{Connection.get_client_ca_list} returns a list containing that
1567 X509Name after the connection is set up.
1568 """
1569 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1570 cadesc = cacert.get_subject()
1571 def single_ca(ctx):
1572 ctx.set_client_ca_list([cadesc])
1573 return [cadesc]
1574 self._check_client_ca_list(single_ca)
1575
1576
1577 def test_set_multiple_ca_list(self):
1578 """
1579 If passed a list containing multiple X509Name objects,
1580 L{Context.set_client_ca_list} configures the context to send those CA
1581 names to the client and, on both the server and client sides,
1582 L{Connection.get_client_ca_list} returns a list containing those
1583 X509Names after the connection is set up.
1584 """
1585 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1586 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1587
1588 sedesc = secert.get_subject()
1589 cldesc = clcert.get_subject()
1590
1591 def multiple_ca(ctx):
1592 L = [sedesc, cldesc]
1593 ctx.set_client_ca_list(L)
1594 return L
1595 self._check_client_ca_list(multiple_ca)
1596
1597
1598 def test_reset_ca_list(self):
1599 """
1600 If called multiple times, only the X509Names passed to the final call
1601 of L{Context.set_client_ca_list} are used to configure the CA names
1602 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001603 """
1604 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1605 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1606 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1607
1608 cadesc = cacert.get_subject()
1609 sedesc = secert.get_subject()
1610 cldesc = clcert.get_subject()
1611
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001612 def changed_ca(ctx):
1613 ctx.set_client_ca_list([sedesc, cldesc])
1614 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001615 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001616 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001617
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001618
1619 def test_mutated_ca_list(self):
1620 """
1621 If the list passed to L{Context.set_client_ca_list} is mutated
1622 afterwards, this does not affect the list of CA names sent to the
1623 client.
1624 """
1625 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1626 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1627
1628 cadesc = cacert.get_subject()
1629 sedesc = secert.get_subject()
1630
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001631 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001632 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001633 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001634 L.append(sedesc)
1635 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001636 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001637
1638
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001639 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001640 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001641 L{Context.add_client_ca} raises L{TypeError} if called with a non-X509
1642 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001643 """
1644 ctx = Context(TLSv1_METHOD)
1645 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001646 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001647 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001648 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001649
1650
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001651 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001652 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001653 A certificate's subject can be added as a CA to be sent to the client
1654 with L{Context.add_client_ca}.
1655 """
1656 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1657 cadesc = cacert.get_subject()
1658 def single_ca(ctx):
1659 ctx.add_client_ca(cacert)
1660 return [cadesc]
1661 self._check_client_ca_list(single_ca)
1662
1663
1664 def test_multiple_add_client_ca(self):
1665 """
1666 Multiple CA names can be sent to the client by calling
1667 L{Context.add_client_ca} with multiple X509 objects.
1668 """
1669 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1670 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1671
1672 cadesc = cacert.get_subject()
1673 sedesc = secert.get_subject()
1674
1675 def multiple_ca(ctx):
1676 ctx.add_client_ca(cacert)
1677 ctx.add_client_ca(secert)
1678 return [cadesc, sedesc]
1679 self._check_client_ca_list(multiple_ca)
1680
1681
1682 def test_set_and_add_client_ca(self):
1683 """
1684 A call to L{Context.set_client_ca_list} followed by a call to
1685 L{Context.add_client_ca} results in using the CA names from the first
1686 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001687 """
1688 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1689 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1690 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1691
1692 cadesc = cacert.get_subject()
1693 sedesc = secert.get_subject()
1694 cldesc = clcert.get_subject()
1695
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001696 def mixed_set_add_ca(ctx):
1697 ctx.set_client_ca_list([cadesc, sedesc])
1698 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001699 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001700 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001701
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001702
1703 def test_set_after_add_client_ca(self):
1704 """
1705 A call to L{Context.set_client_ca_list} after a call to
1706 L{Context.add_client_ca} replaces the CA name specified by the former
1707 call with the names specified by the latter cal.
1708 """
1709 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1710 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1711 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1712
1713 cadesc = cacert.get_subject()
1714 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001715
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001716 def set_replaces_add_ca(ctx):
1717 ctx.add_client_ca(clcert)
1718 ctx.set_client_ca_list([cadesc])
1719 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001720 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001721 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001722
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001723
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04001724class InfoConstantTests(TestCase):
1725 """
1726 Tests for assorted constants exposed for use in info callbacks.
1727 """
1728 def test_integers(self):
1729 """
1730 All of the info constants are integers.
1731
1732 This is a very weak test. It would be nice to have one that actually
1733 verifies that as certain info events happen, the value passed to the
1734 info callback matches up with the constant exposed by OpenSSL.SSL.
1735 """
1736 for const in [
1737 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
1738 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
1739 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
1740 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
1741 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
1742 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
1743
1744 self.assertTrue(isinstance(const, int))
1745
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001746
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001747if __name__ == '__main__':
1748 main()