blob: bd5a92b092efa0e0aee422ad5901fd87d9bd0393 [file] [log] [blame]
Jean-Paul Calderone7526d172010-09-09 17:55:31 -04001# Copyright (C) Jean-Paul Calderone 2008-2010, All rights reserved
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04002
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04003"""
4Unit tests for L{OpenSSL.SSL}.
5"""
6
Jean-Paul Calderone8322d782010-09-17 19:22:31 -04007from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK
Jean-Paul Calderone52f0d8b2009-03-07 09:10:19 -05008from sys import platform
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04009from socket import error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040010from os import makedirs
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -040011from os.path import join
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040012from unittest import main
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050013
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040014from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM, FILETYPE_ASN1
15from OpenSSL.crypto import PKey, X509, X509Extension
16from OpenSSL.crypto import dump_privatekey, load_privatekey
17from OpenSSL.crypto import dump_certificate, load_certificate
18
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040019from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040020from OpenSSL.SSL import SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD
Jean-Paul Calderone68649052009-07-17 21:14:27 -040021from OpenSSL.SSL import OP_NO_SSLv2, OP_NO_SSLv3, OP_SINGLE_DH_USE
Rick Deanb71c0d22009-04-01 14:09:23 -050022from OpenSSL.SSL import VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040023from OpenSSL.SSL import Error, SysCallError, WantReadError, ZeroReturnError
24from OpenSSL.SSL import Context, ContextType, Connection, ConnectionType
25
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -040026from OpenSSL.test.util import TestCase, bytes, b
Jean-Paul Calderone18808652009-07-05 12:54:05 -040027from OpenSSL.test.test_crypto import cleartextCertificatePEM, cleartextPrivateKeyPEM
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040028from OpenSSL.test.test_crypto import client_cert_pem, client_key_pem
29from OpenSSL.test.test_crypto import server_cert_pem, server_key_pem, root_cert_pem
30
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050031try:
32 from OpenSSL.SSL import OP_NO_QUERY_MTU
33except ImportError:
34 OP_NO_QUERY_MTU = None
35try:
36 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
37except ImportError:
38 OP_COOKIE_EXCHANGE = None
39try:
40 from OpenSSL.SSL import OP_NO_TICKET
41except ImportError:
42 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040043
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040044
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040045# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
46# to use)
47dhparam = """\
48-----BEGIN DH PARAMETERS-----
49MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
50-----END DH PARAMETERS-----
51"""
52
53
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040054def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040055 return ok
56
Rick Deanb1ccd562009-07-09 23:52:39 -050057def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040058 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -040059 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040060 """
61 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -050062 port = socket()
63 port.bind(('', 0))
64 port.listen(1)
65 client = socket()
66 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -040067 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040068 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -050069 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -050070
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040071 # Let's pass some unencrypted data to make sure our socket connection is
72 # fine. Just one byte, so we don't have to worry about buffers getting
73 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -040074 server.send(b("x"))
75 assert client.recv(1024) == b("x")
76 client.send(b("y"))
77 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -050078
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -040079 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040080 server.setblocking(False)
81 client.setblocking(False)
82
Rick Deanb1ccd562009-07-09 23:52:39 -050083 return (server, client)
84
85
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040086
Jean-Paul Calderonef8742032010-09-25 00:00:32 -040087def handshake(client, server):
88 conns = [client, server]
89 while conns:
90 for conn in conns:
91 try:
92 conn.do_handshake()
93 except WantReadError:
94 pass
95 else:
96 conns.remove(conn)
97
98
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040099class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400100 """
101 Helper mixin which defines methods for creating a connected socket pair and
102 for forcing two connected SSL sockets to talk to each other via memory BIOs.
103 """
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400104 def _loopback(self):
105 (server, client) = socket_pair()
106
107 ctx = Context(TLSv1_METHOD)
108 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
109 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
110 server = Connection(ctx, server)
111 server.set_accept_state()
112 client = Connection(Context(TLSv1_METHOD), client)
113 client.set_connect_state()
114
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400115 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400116
117 server.setblocking(True)
118 client.setblocking(True)
119 return server, client
120
121
122 def _interactInMemory(self, client_conn, server_conn):
123 """
124 Try to read application bytes from each of the two L{Connection}
125 objects. Copy bytes back and forth between their send/receive buffers
126 for as long as there is anything to copy. When there is nothing more
127 to copy, return C{None}. If one of them actually manages to deliver
128 some application bytes, return a two-tuple of the connection from which
129 the bytes were read and the bytes themselves.
130 """
131 wrote = True
132 while wrote:
133 # Loop until neither side has anything to say
134 wrote = False
135
136 # Copy stuff from each side's send buffer to the other side's
137 # receive buffer.
138 for (read, write) in [(client_conn, server_conn),
139 (server_conn, client_conn)]:
140
141 # Give the side a chance to generate some more bytes, or
142 # succeed.
143 try:
144 bytes = read.recv(2 ** 16)
145 except WantReadError:
146 # It didn't succeed, so we'll hope it generated some
147 # output.
148 pass
149 else:
150 # It did succeed, so we'll stop now and let the caller deal
151 # with it.
152 return (read, bytes)
153
154 while True:
155 # Keep copying as long as there's more stuff there.
156 try:
157 dirty = read.bio_read(4096)
158 except WantReadError:
159 # Okay, nothing more waiting to be sent. Stop
160 # processing this send buffer.
161 break
162 else:
163 # Keep track of the fact that someone generated some
164 # output.
165 wrote = True
166 write.bio_write(dirty)
167
168
169
170class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400171 """
172 Unit tests for L{OpenSSL.SSL.Context}.
173 """
174 def test_method(self):
175 """
176 L{Context} can be instantiated with one of L{SSLv2_METHOD},
177 L{SSLv3_METHOD}, L{SSLv23_METHOD}, or L{TLSv1_METHOD}.
178 """
179 for meth in [SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]:
180 Context(meth)
181 self.assertRaises(TypeError, Context, "")
182 self.assertRaises(ValueError, Context, 10)
183
184
Rick Deane15b1472009-07-09 15:53:42 -0500185 def test_type(self):
186 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400187 L{Context} and L{ContextType} refer to the same type object and can be
188 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500189 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400190 self.assertIdentical(Context, ContextType)
191 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500192
193
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400194 def test_use_privatekey(self):
195 """
196 L{Context.use_privatekey} takes an L{OpenSSL.crypto.PKey} instance.
197 """
198 key = PKey()
199 key.generate_key(TYPE_RSA, 128)
200 ctx = Context(TLSv1_METHOD)
201 ctx.use_privatekey(key)
202 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400203
204
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400205 def test_set_app_data_wrong_args(self):
206 """
207 L{Context.set_app_data} raises L{TypeError} if called with other than
208 one argument.
209 """
210 context = Context(TLSv1_METHOD)
211 self.assertRaises(TypeError, context.set_app_data)
212 self.assertRaises(TypeError, context.set_app_data, None, None)
213
214
215 def test_get_app_data_wrong_args(self):
216 """
217 L{Context.get_app_data} raises L{TypeError} if called with any
218 arguments.
219 """
220 context = Context(TLSv1_METHOD)
221 self.assertRaises(TypeError, context.get_app_data, None)
222
223
224 def test_app_data(self):
225 """
226 L{Context.set_app_data} stores an object for later retrieval using
227 L{Context.get_app_data}.
228 """
229 app_data = object()
230 context = Context(TLSv1_METHOD)
231 context.set_app_data(app_data)
232 self.assertIdentical(context.get_app_data(), app_data)
233
234
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400235 def test_set_options_wrong_args(self):
236 """
237 L{Context.set_options} raises L{TypeError} if called with the wrong
238 number of arguments or a non-C{int} argument.
239 """
240 context = Context(TLSv1_METHOD)
241 self.assertRaises(TypeError, context.set_options)
242 self.assertRaises(TypeError, context.set_options, None)
243 self.assertRaises(TypeError, context.set_options, 1, None)
244
245
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400246 def test_set_timeout_wrong_args(self):
247 """
248 L{Context.set_timeout} raises L{TypeError} if called with the wrong
249 number of arguments or a non-C{int} argument.
250 """
251 context = Context(TLSv1_METHOD)
252 self.assertRaises(TypeError, context.set_timeout)
253 self.assertRaises(TypeError, context.set_timeout, None)
254 self.assertRaises(TypeError, context.set_timeout, 1, None)
255
256
257 def test_get_timeout_wrong_args(self):
258 """
259 L{Context.get_timeout} raises L{TypeError} if called with any arguments.
260 """
261 context = Context(TLSv1_METHOD)
262 self.assertRaises(TypeError, context.get_timeout, None)
263
264
265 def test_timeout(self):
266 """
267 L{Context.set_timeout} sets the session timeout for all connections
268 created using the context object. L{Context.get_timeout} retrieves this
269 value.
270 """
271 context = Context(TLSv1_METHOD)
272 context.set_timeout(1234)
273 self.assertEquals(context.get_timeout(), 1234)
274
275
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400276 def test_set_verify_depth_wrong_args(self):
277 """
278 L{Context.set_verify_depth} raises L{TypeError} if called with the wrong
279 number of arguments or a non-C{int} argument.
280 """
281 context = Context(TLSv1_METHOD)
282 self.assertRaises(TypeError, context.set_verify_depth)
283 self.assertRaises(TypeError, context.set_verify_depth, None)
284 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
285
286
287 def test_get_verify_depth_wrong_args(self):
288 """
289 L{Context.get_verify_depth} raises L{TypeError} if called with any arguments.
290 """
291 context = Context(TLSv1_METHOD)
292 self.assertRaises(TypeError, context.get_verify_depth, None)
293
294
295 def test_verify_depth(self):
296 """
297 L{Context.set_verify_depth} sets the number of certificates in a chain
298 to follow before giving up. The value can be retrieved with
299 L{Context.get_verify_depth}.
300 """
301 context = Context(TLSv1_METHOD)
302 context.set_verify_depth(11)
303 self.assertEquals(context.get_verify_depth(), 11)
304
305
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400306 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400307 """
308 Write a new private key out to a new file, encrypted using the given
309 passphrase. Return the path to the new file.
310 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400311 key = PKey()
312 key.generate_key(TYPE_RSA, 128)
313 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400314 fObj = open(pemFile, 'w')
315 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
316 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400317 fObj.close()
318 return pemFile
319
320
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400321 def test_set_passwd_cb_wrong_args(self):
322 """
323 L{Context.set_passwd_cb} raises L{TypeError} if called with the
324 wrong arguments or with a non-callable first argument.
325 """
326 context = Context(TLSv1_METHOD)
327 self.assertRaises(TypeError, context.set_passwd_cb)
328 self.assertRaises(TypeError, context.set_passwd_cb, None)
329 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
330
331
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400332 def test_set_passwd_cb(self):
333 """
334 L{Context.set_passwd_cb} accepts a callable which will be invoked when
335 a private key is loaded from an encrypted PEM.
336 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400337 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400338 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400339 calledWith = []
340 def passphraseCallback(maxlen, verify, extra):
341 calledWith.append((maxlen, verify, extra))
342 return passphrase
343 context = Context(TLSv1_METHOD)
344 context.set_passwd_cb(passphraseCallback)
345 context.use_privatekey_file(pemFile)
346 self.assertTrue(len(calledWith), 1)
347 self.assertTrue(isinstance(calledWith[0][0], int))
348 self.assertTrue(isinstance(calledWith[0][1], int))
349 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400350
351
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400352 def test_passwd_callback_exception(self):
353 """
354 L{Context.use_privatekey_file} propagates any exception raised by the
355 passphrase callback.
356 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400357 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400358 def passphraseCallback(maxlen, verify, extra):
359 raise RuntimeError("Sorry, I am a fail.")
360
361 context = Context(TLSv1_METHOD)
362 context.set_passwd_cb(passphraseCallback)
363 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
364
365
366 def test_passwd_callback_false(self):
367 """
368 L{Context.use_privatekey_file} raises L{OpenSSL.SSL.Error} if the
369 passphrase callback returns a false value.
370 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400371 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400372 def passphraseCallback(maxlen, verify, extra):
373 return None
374
375 context = Context(TLSv1_METHOD)
376 context.set_passwd_cb(passphraseCallback)
377 self.assertRaises(Error, context.use_privatekey_file, pemFile)
378
379
380 def test_passwd_callback_non_string(self):
381 """
382 L{Context.use_privatekey_file} raises L{OpenSSL.SSL.Error} if the
383 passphrase callback returns a true non-string value.
384 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400385 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400386 def passphraseCallback(maxlen, verify, extra):
387 return 10
388
389 context = Context(TLSv1_METHOD)
390 context.set_passwd_cb(passphraseCallback)
391 self.assertRaises(Error, context.use_privatekey_file, pemFile)
392
393
394 def test_passwd_callback_too_long(self):
395 """
396 If the passphrase returned by the passphrase callback returns a string
397 longer than the indicated maximum length, it is truncated.
398 """
399 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400400 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400401 pemFile = self._write_encrypted_pem(passphrase)
402 def passphraseCallback(maxlen, verify, extra):
403 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400404 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400405
406 context = Context(TLSv1_METHOD)
407 context.set_passwd_cb(passphraseCallback)
408 # This shall succeed because the truncated result is the correct
409 # passphrase.
410 context.use_privatekey_file(pemFile)
411
412
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400413 def test_set_info_callback(self):
414 """
415 L{Context.set_info_callback} accepts a callable which will be invoked
416 when certain information about an SSL connection is available.
417 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500418 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400419
420 clientSSL = Connection(Context(TLSv1_METHOD), client)
421 clientSSL.set_connect_state()
422
423 called = []
424 def info(conn, where, ret):
425 called.append((conn, where, ret))
426 context = Context(TLSv1_METHOD)
427 context.set_info_callback(info)
428 context.use_certificate(
429 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
430 context.use_privatekey(
431 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
432
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400433 serverSSL = Connection(context, server)
434 serverSSL.set_accept_state()
435
436 while not called:
437 for ssl in clientSSL, serverSSL:
438 try:
439 ssl.do_handshake()
440 except WantReadError:
441 pass
442
443 # Kind of lame. Just make sure it got called somehow.
444 self.assertTrue(called)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400445
446
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400447 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400448 """
449 Create a client context which will verify the peer certificate and call
450 its C{load_verify_locations} method with C{*args}. Then connect it to a
451 server and ensure that the handshake succeeds.
452 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500453 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400454
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400455 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400456 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400457 # Require that the server certificate verify properly or the
458 # connection will fail.
459 clientContext.set_verify(
460 VERIFY_PEER,
461 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
462
463 clientSSL = Connection(clientContext, client)
464 clientSSL.set_connect_state()
465
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400466 serverContext = Context(TLSv1_METHOD)
467 serverContext.use_certificate(
468 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
469 serverContext.use_privatekey(
470 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
471
472 serverSSL = Connection(serverContext, server)
473 serverSSL.set_accept_state()
474
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400475 # Without load_verify_locations above, the handshake
476 # will fail:
477 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
478 # 'certificate verify failed')]
479 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400480
481 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400482 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400483
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500484
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400485 def test_load_verify_file(self):
486 """
487 L{Context.load_verify_locations} accepts a file name and uses the
488 certificates within for verification purposes.
489 """
490 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400491 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400492 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400493 fObj.close()
494
495 self._load_verify_locations_test(cafile)
496
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400497
498 def test_load_verify_invalid_file(self):
499 """
500 L{Context.load_verify_locations} raises L{Error} when passed a
501 non-existent cafile.
502 """
503 clientContext = Context(TLSv1_METHOD)
504 self.assertRaises(
505 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400506
507
508 def test_load_verify_directory(self):
509 """
510 L{Context.load_verify_locations} accepts a directory name and uses
511 the certificates within for verification purposes.
512 """
513 capath = self.mktemp()
514 makedirs(capath)
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -0400515 # Hash value computed manually with c_rehash to avoid depending on
516 # c_rehash in the test suite.
517 cafile = join(capath, 'c7adac82.0')
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400518 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400519 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400520 fObj.close()
521
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400522 self._load_verify_locations_test(None, capath)
523
524
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400525 def test_load_verify_locations_wrong_args(self):
526 """
527 L{Context.load_verify_locations} raises L{TypeError} if called with
528 the wrong number of arguments or with non-C{str} arguments.
529 """
530 context = Context(TLSv1_METHOD)
531 self.assertRaises(TypeError, context.load_verify_locations)
532 self.assertRaises(TypeError, context.load_verify_locations, object())
533 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
534 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
535
536
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400537 if platform == "win32":
538 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400539 "See LP#404343 and LP#404344."
540 else:
541 def test_set_default_verify_paths(self):
542 """
543 L{Context.set_default_verify_paths} causes the platform-specific CA
544 certificate locations to be used for verification purposes.
545 """
546 # Testing this requires a server with a certificate signed by one of
547 # the CAs in the platform CA location. Getting one of those costs
548 # money. Fortunately (or unfortunately, depending on your
549 # perspective), it's easy to think of a public server on the
550 # internet which has such a certificate. Connecting to the network
551 # in a unit test is bad, but it's the only way I can think of to
552 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400553
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400554 # Arg, verisign.com doesn't speak TLSv1
555 context = Context(SSLv3_METHOD)
556 context.set_default_verify_paths()
557 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200558 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400559 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400560
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400561 client = socket()
562 client.connect(('verisign.com', 443))
563 clientSSL = Connection(context, client)
564 clientSSL.set_connect_state()
565 clientSSL.do_handshake()
566 clientSSL.send('GET / HTTP/1.0\r\n\r\n')
567 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400568
569
570 def test_set_default_verify_paths_signature(self):
571 """
572 L{Context.set_default_verify_paths} takes no arguments and raises
573 L{TypeError} if given any.
574 """
575 context = Context(TLSv1_METHOD)
576 self.assertRaises(TypeError, context.set_default_verify_paths, None)
577 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
578 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500579
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400580
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500581 def test_add_extra_chain_cert_invalid_cert(self):
582 """
583 L{Context.add_extra_chain_cert} raises L{TypeError} if called with
584 other than one argument or if called with an object which is not an
585 instance of L{X509}.
586 """
587 context = Context(TLSv1_METHOD)
588 self.assertRaises(TypeError, context.add_extra_chain_cert)
589 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
590 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
591
592
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400593 def _create_certificate_chain(self):
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500594 """
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400595 Construct and return a chain of certificates.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400596
597 1. A new self-signed certificate authority certificate (cacert)
598 2. A new intermediate certificate signed by cacert (icert)
599 3. A new server certificate signed by icert (scert)
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500600 """
Jean-Paul Calderone9b0744c2010-09-14 18:11:01 -0400601 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500602
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400603 # Step 1
604 cakey = PKey()
605 cakey.generate_key(TYPE_RSA, 512)
606 cacert = X509()
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400607 cacert.get_subject().commonName = "Authority Certificate"
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400608 cacert.set_issuer(cacert.get_subject())
609 cacert.set_pubkey(cakey)
Jean-Paul Calderone4e6aed62010-09-19 10:05:34 -0400610 cacert.set_notBefore(b("20000101000000Z"))
611 cacert.set_notAfter(b("20200101000000Z"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400612 cacert.add_extensions([caext])
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400613 cacert.set_serial_number(0)
614 cacert.sign(cakey, "sha1")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500615
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400616 # Step 2
617 ikey = PKey()
618 ikey.generate_key(TYPE_RSA, 512)
619 icert = X509()
620 icert.get_subject().commonName = "Intermediate Certificate"
621 icert.set_issuer(cacert.get_subject())
622 icert.set_pubkey(ikey)
Jean-Paul Calderone4e6aed62010-09-19 10:05:34 -0400623 icert.set_notBefore(b("20000101000000Z"))
624 icert.set_notAfter(b("20200101000000Z"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400625 icert.add_extensions([caext])
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400626 icert.set_serial_number(0)
627 icert.sign(cakey, "sha1")
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400628
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400629 # Step 3
630 skey = PKey()
631 skey.generate_key(TYPE_RSA, 512)
632 scert = X509()
633 scert.get_subject().commonName = "Server Certificate"
634 scert.set_issuer(icert.get_subject())
635 scert.set_pubkey(skey)
Jean-Paul Calderone4e6aed62010-09-19 10:05:34 -0400636 scert.set_notBefore(b("20000101000000Z"))
637 scert.set_notAfter(b("20200101000000Z"))
Jean-Paul Calderone2db1de52010-09-19 10:08:13 -0400638 scert.add_extensions([
639 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400640 scert.set_serial_number(0)
641 scert.sign(ikey, "sha1")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400642
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400643 return [(cakey, cacert), (ikey, icert), (skey, scert)]
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400644
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400645
646 def _handshake_test(self, serverContext, clientContext):
647 """
648 Verify that a client and server created with the given contexts can
649 successfully handshake and communicate.
650 """
651 serverSocket, clientSocket = socket_pair()
652
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400653 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400654 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400655
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400656 client = Connection(clientContext, clientSocket)
657 client.set_connect_state()
658
659 # Make them talk to each other.
660 # self._interactInMemory(client, server)
661 for i in range(3):
662 for s in [client, server]:
663 try:
664 s.do_handshake()
665 except WantReadError:
666 pass
667
668
669 def test_add_extra_chain_cert(self):
670 """
671 L{Context.add_extra_chain_cert} accepts an L{X509} instance to add to
672 the certificate chain.
673
674 See L{_create_certificate_chain} for the details of the certificate
675 chain tested.
676
677 The chain is tested by starting a server with scert and connecting
678 to it with a client which trusts cacert and requires verification to
679 succeed.
680 """
681 chain = self._create_certificate_chain()
682 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
683
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400684 # Dump the CA certificate to a file because that's the only way to load
685 # it as a trusted CA in the client context.
686 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400687 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400688 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400689 fObj.close()
690
691 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400692 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400693 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400694 fObj.close()
695
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400696 # Create the server context
697 serverContext = Context(TLSv1_METHOD)
698 serverContext.use_privatekey(skey)
699 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400700 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400701 serverContext.add_extra_chain_cert(icert)
702
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400703 # Create the client
704 clientContext = Context(TLSv1_METHOD)
705 clientContext.set_verify(
706 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
707 clientContext.load_verify_locations('ca.pem')
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400708
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400709 # Try it out.
710 self._handshake_test(serverContext, clientContext)
711
712
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400713 def test_use_certificate_chain_file(self):
714 """
715 L{Context.use_certificate_chain_file} reads a certificate chain from
716 the specified file.
717
718 The chain is tested by starting a server with scert and connecting
719 to it with a client which trusts cacert and requires verification to
720 succeed.
721 """
722 chain = self._create_certificate_chain()
723 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
724
725 # Write out the chain file.
726 chainFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400727 fObj = open(chainFile, 'w')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400728 # Most specific to least general.
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400729 fObj.write(dump_certificate(FILETYPE_PEM, scert).decode('ascii'))
730 fObj.write(dump_certificate(FILETYPE_PEM, icert).decode('ascii'))
731 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400732 fObj.close()
733
734 serverContext = Context(TLSv1_METHOD)
735 serverContext.use_certificate_chain_file(chainFile)
736 serverContext.use_privatekey(skey)
737
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400738 fObj = open('ca.pem', 'w')
739 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400740 fObj.close()
741
742 clientContext = Context(TLSv1_METHOD)
743 clientContext.set_verify(
744 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
745 clientContext.load_verify_locations('ca.pem')
746
747 self._handshake_test(serverContext, clientContext)
748
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -0400749 # XXX load_client_ca
750 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -0400751
752 def test_get_verify_mode_wrong_args(self):
753 """
754 L{Context.get_verify_mode} raises L{TypeError} if called with any
755 arguments.
756 """
757 context = Context(TLSv1_METHOD)
758 self.assertRaises(TypeError, context.get_verify_mode, None)
759
760
761 def test_get_verify_mode(self):
762 """
763 L{Context.get_verify_mode} returns the verify mode flags previously
764 passed to L{Context.set_verify}.
765 """
766 context = Context(TLSv1_METHOD)
767 self.assertEquals(context.get_verify_mode(), 0)
768 context.set_verify(
769 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
770 self.assertEquals(
771 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
772
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400773
774 def test_load_tmp_dh_wrong_args(self):
775 """
776 L{Context.load_tmp_dh} raises L{TypeError} if called with the wrong
777 number of arguments or with a non-C{str} argument.
778 """
779 context = Context(TLSv1_METHOD)
780 self.assertRaises(TypeError, context.load_tmp_dh)
781 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
782 self.assertRaises(TypeError, context.load_tmp_dh, object())
783
784
785 def test_load_tmp_dh_missing_file(self):
786 """
787 L{Context.load_tmp_dh} raises L{OpenSSL.SSL.Error} if the specified file
788 does not exist.
789 """
790 context = Context(TLSv1_METHOD)
791 self.assertRaises(Error, context.load_tmp_dh, "hello")
792
793
794 def test_load_tmp_dh(self):
795 """
796 L{Context.load_tmp_dh} loads Diffie-Hellman parameters from the
797 specified file.
798 """
799 context = Context(TLSv1_METHOD)
800 dhfilename = self.mktemp()
801 dhfile = open(dhfilename, "w")
802 dhfile.write(dhparam)
803 dhfile.close()
804 context.load_tmp_dh(dhfilename)
805 # XXX What should I assert here? -exarkun
806
807
808 def test_set_cipher_list(self):
809 """
810 L{Context.set_cipher_list} accepts a C{str} naming the ciphers which
811 connections created with the context object will be able to choose from.
812 """
813 context = Context(TLSv1_METHOD)
814 context.set_cipher_list("hello world:EXP-RC4-MD5")
815 conn = Connection(context, None)
816 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400817
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400818
819
820class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -0500821 """
822 Unit tests for L{OpenSSL.SSL.Connection}.
823 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -0400824 # XXX want_write
825 # XXX want_read
826 # XXX get_peer_certificate -> None
827 # XXX sock_shutdown
828 # XXX master_key -> TypeError
829 # XXX server_random -> TypeError
830 # XXX state_string
831 # XXX connect -> TypeError
832 # XXX connect_ex -> TypeError
833 # XXX set_connect_state -> TypeError
834 # XXX set_accept_state -> TypeError
835 # XXX renegotiate_pending
836 # XXX do_handshake -> TypeError
837 # XXX bio_read -> TypeError
838 # XXX recv -> TypeError
839 # XXX send -> TypeError
840 # XXX bio_write -> TypeError
841
Rick Deane15b1472009-07-09 15:53:42 -0500842 def test_type(self):
843 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400844 L{Connection} and L{ConnectionType} refer to the same type object and
845 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500846 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400847 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -0500848 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400849 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -0500850
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400851
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -0500852 def test_get_context(self):
853 """
854 L{Connection.get_context} returns the L{Context} instance used to
855 construct the L{Connection} instance.
856 """
857 context = Context(TLSv1_METHOD)
858 connection = Connection(context, None)
859 self.assertIdentical(connection.get_context(), context)
860
861
862 def test_get_context_wrong_args(self):
863 """
864 L{Connection.get_context} raises L{TypeError} if called with any
865 arguments.
866 """
867 connection = Connection(Context(TLSv1_METHOD), None)
868 self.assertRaises(TypeError, connection.get_context, None)
869
870
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -0400871 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400872 """
873 L{Connection.pending} returns the number of bytes available for
874 immediate read.
875 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -0400876 connection = Connection(Context(TLSv1_METHOD), None)
877 self.assertEquals(connection.pending(), 0)
878
879
880 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400881 """
882 L{Connection.pending} raises L{TypeError} if called with any arguments.
883 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -0400884 connection = Connection(Context(TLSv1_METHOD), None)
885 self.assertRaises(TypeError, connection.pending, None)
886
887
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400888 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400889 """
890 L{Connection.connect} raises L{TypeError} if called with a non-address
891 argument or with the wrong number of arguments.
892 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400893 connection = Connection(Context(TLSv1_METHOD), socket())
894 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400895 self.assertRaises(TypeError, connection.connect)
896 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400897
898
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400899 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400900 """
901 L{Connection.connect} raises L{socket.error} if the underlying socket
902 connect method raises it.
903 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400904 client = socket()
905 context = Context(TLSv1_METHOD)
906 clientSSL = Connection(context, client)
907 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -0400908 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400909
910
911 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400912 """
913 L{Connection.connect} establishes a connection to the specified address.
914 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400915 port = socket()
916 port.bind(('', 0))
917 port.listen(3)
918
919 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -0400920 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
921 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400922
923
Jean-Paul Calderone7b614872010-09-24 17:43:44 -0400924 if platform == "darwin":
925 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
926 else:
927 def test_connect_ex(self):
928 """
929 If there is a connection error, L{Connection.connect_ex} returns the
930 errno instead of raising an exception.
931 """
932 port = socket()
933 port.bind(('', 0))
934 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -0400935
Jean-Paul Calderone7b614872010-09-24 17:43:44 -0400936 clientSSL = Connection(Context(TLSv1_METHOD), socket())
937 clientSSL.setblocking(False)
938 result = clientSSL.connect_ex(port.getsockname())
939 expected = (EINPROGRESS, EWOULDBLOCK)
940 self.assertTrue(
941 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -0400942
943
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400944 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400945 """
946 L{Connection.accept} raises L{TypeError} if called with any arguments.
947 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400948 connection = Connection(Context(TLSv1_METHOD), socket())
949 self.assertRaises(TypeError, connection.accept, None)
950
951
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400952 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400953 """
954 L{Connection.accept} accepts a pending connection attempt and returns a
955 tuple of a new L{Connection} (the accepted client) and the address the
956 connection originated from.
957 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400958 ctx = Context(TLSv1_METHOD)
959 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
960 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400961 port = socket()
962 portSSL = Connection(ctx, port)
963 portSSL.bind(('', 0))
964 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400965
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400966 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -0400967
968 # Calling portSSL.getsockname() here to get the server IP address sounds
969 # great, but frequently fails on Windows.
970 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400971
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400972 serverSSL, address = portSSL.accept()
973
974 self.assertTrue(isinstance(serverSSL, Connection))
975 self.assertIdentical(serverSSL.get_context(), ctx)
976 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400977
978
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400979 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400980 """
981 L{Connection.shutdown} raises L{TypeError} if called with the wrong
982 number of arguments or with arguments other than integers.
983 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400984 connection = Connection(Context(TLSv1_METHOD), None)
985 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -0400986 self.assertRaises(TypeError, connection.get_shutdown, None)
987 self.assertRaises(TypeError, connection.set_shutdown)
988 self.assertRaises(TypeError, connection.set_shutdown, None)
989 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400990
991
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400992 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400993 """
994 L{Connection.shutdown} performs an SSL-level connection shutdown.
995 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400996 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -0400997 self.assertFalse(server.shutdown())
998 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400999 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001000 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1001 client.shutdown()
1002 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1003 self.assertRaises(ZeroReturnError, server.recv, 1024)
1004 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001005
1006
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001007 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001008 """
1009 L{Connection.set_shutdown} sets the state of the SSL connection shutdown
1010 process.
1011 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001012 connection = Connection(Context(TLSv1_METHOD), socket())
1013 connection.set_shutdown(RECEIVED_SHUTDOWN)
1014 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1015
1016
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001017 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001018 """
1019 L{Connection.set_app_data} raises L{TypeError} if called with other than
1020 one argument. L{Connection.get_app_data} raises L{TypeError} if called
1021 with any arguments.
1022 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001023 conn = Connection(Context(TLSv1_METHOD), None)
1024 self.assertRaises(TypeError, conn.get_app_data, None)
1025 self.assertRaises(TypeError, conn.set_app_data)
1026 self.assertRaises(TypeError, conn.set_app_data, None, None)
1027
1028
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001029 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001030 """
1031 Any object can be set as app data by passing it to
1032 L{Connection.set_app_data} and later retrieved with
1033 L{Connection.get_app_data}.
1034 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001035 conn = Connection(Context(TLSv1_METHOD), None)
1036 app_data = object()
1037 conn.set_app_data(app_data)
1038 self.assertIdentical(conn.get_app_data(), app_data)
1039
1040
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001041 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001042 """
1043 L{Connection.makefile} is not implemented and calling that method raises
1044 L{NotImplementedError}.
1045 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001046 conn = Connection(Context(TLSv1_METHOD), None)
1047 self.assertRaises(NotImplementedError, conn.makefile)
1048
1049
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001050
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001051class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001052 """
1053 Tests for L{Connection.get_cipher_list}.
1054 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04001055 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001056 """
1057 L{Connection.get_cipher_list} raises L{TypeError} if called with any
1058 arguments.
1059 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001060 connection = Connection(Context(TLSv1_METHOD), None)
1061 self.assertRaises(TypeError, connection.get_cipher_list, None)
1062
1063
1064 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001065 """
1066 L{Connection.get_cipher_list} returns a C{list} of C{str} giving the
1067 names of the ciphers which might be used.
1068 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001069 connection = Connection(Context(TLSv1_METHOD), None)
1070 ciphers = connection.get_cipher_list()
1071 self.assertTrue(isinstance(ciphers, list))
1072 for cipher in ciphers:
1073 self.assertTrue(isinstance(cipher, str))
1074
1075
1076
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001077class ConnectionSendTests(TestCase, _LoopbackMixin):
1078 """
1079 Tests for L{Connection.send}
1080 """
1081 def test_wrong_args(self):
1082 """
1083 When called with arguments other than a single string,
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05001084 L{Connection.send} raises L{TypeError}.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001085 """
1086 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05001087 self.assertRaises(TypeError, connection.send)
1088 self.assertRaises(TypeError, connection.send, object())
1089 self.assertRaises(TypeError, connection.send, "foo", "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001090
1091
1092 def test_short_bytes(self):
1093 """
1094 When passed a short byte string, L{Connection.send} transmits all of it
1095 and returns the number of bytes sent.
1096 """
1097 server, client = self._loopback()
1098 count = server.send(b('xy'))
1099 self.assertEquals(count, 2)
1100 self.assertEquals(client.recv(2), b('xy'))
1101
1102 try:
1103 memoryview
1104 except NameError:
1105 "cannot test sending memoryview without memoryview"
1106 else:
1107 def test_short_memoryview(self):
1108 """
1109 When passed a memoryview onto a small number of bytes,
1110 L{Connection.send} transmits all of them and returns the number of
1111 bytes sent.
1112 """
1113 server, client = self._loopback()
1114 count = server.send(memoryview(b('xy')))
1115 self.assertEquals(count, 2)
1116 self.assertEquals(client.recv(2), b('xy'))
1117
1118
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001119
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001120class ConnectionSendallTests(TestCase, _LoopbackMixin):
1121 """
1122 Tests for L{Connection.sendall}.
1123 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001124 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001125 """
1126 When called with arguments other than a single string,
1127 L{Connection.sendall} raises L{TypeError}.
1128 """
1129 connection = Connection(Context(TLSv1_METHOD), None)
1130 self.assertRaises(TypeError, connection.sendall)
1131 self.assertRaises(TypeError, connection.sendall, object())
1132 self.assertRaises(TypeError, connection.sendall, "foo", "bar")
1133
1134
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001135 def test_short(self):
1136 """
1137 L{Connection.sendall} transmits all of the bytes in the string passed to
1138 it.
1139 """
1140 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001141 server.sendall(b('x'))
1142 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001143
1144
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001145 try:
1146 memoryview
1147 except NameError:
1148 "cannot test sending memoryview without memoryview"
1149 else:
1150 def test_short_memoryview(self):
1151 """
1152 When passed a memoryview onto a small number of bytes,
1153 L{Connection.sendall} transmits all of them.
1154 """
1155 server, client = self._loopback()
1156 server.sendall(memoryview(b('x')))
1157 self.assertEquals(client.recv(1), b('x'))
1158
1159
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001160 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001161 """
1162 L{Connection.sendall} transmits all of the bytes in the string passed to
1163 it even if this requires multiple calls of an underlying write function.
1164 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001165 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04001166 # Should be enough, underlying SSL_write should only do 16k at a time.
1167 # On Windows, after 32k of bytes the write will block (forever - because
1168 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04001169 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001170 server.sendall(message)
1171 accum = []
1172 received = 0
1173 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001174 data = client.recv(1024)
1175 accum.append(data)
1176 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04001177 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001178
1179
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001180 def test_closed(self):
1181 """
1182 If the underlying socket is closed, L{Connection.sendall} propagates the
1183 write error from the low level write call.
1184 """
1185 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04001186 server.sock_shutdown(2)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001187 self.assertRaises(SysCallError, server.sendall, "hello, world")
1188
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001189
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001190
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001191class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
1192 """
1193 Tests for SSL renegotiation APIs.
1194 """
1195 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001196 """
1197 L{Connection.renegotiate} raises L{TypeError} if called with any
1198 arguments.
1199 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001200 connection = Connection(Context(TLSv1_METHOD), None)
1201 self.assertRaises(TypeError, connection.renegotiate, None)
1202
1203
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001204 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001205 """
1206 L{Connection.total_renegotiations} raises L{TypeError} if called with
1207 any arguments.
1208 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001209 connection = Connection(Context(TLSv1_METHOD), None)
1210 self.assertRaises(TypeError, connection.total_renegotiations, None)
1211
1212
1213 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001214 """
1215 L{Connection.total_renegotiations} returns C{0} before any
1216 renegotiations have happened.
1217 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001218 connection = Connection(Context(TLSv1_METHOD), None)
1219 self.assertEquals(connection.total_renegotiations(), 0)
1220
1221
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001222# def test_renegotiate(self):
1223# """
1224# """
1225# server, client = self._loopback()
1226
1227# server.send("hello world")
1228# self.assertEquals(client.recv(len("hello world")), "hello world")
1229
1230# self.assertEquals(server.total_renegotiations(), 0)
1231# self.assertTrue(server.renegotiate())
1232
1233# server.setblocking(False)
1234# client.setblocking(False)
1235# while server.renegotiate_pending():
1236# client.do_handshake()
1237# server.do_handshake()
1238
1239# self.assertEquals(server.total_renegotiations(), 1)
1240
1241
1242
1243
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001244class ErrorTests(TestCase):
1245 """
1246 Unit tests for L{OpenSSL.SSL.Error}.
1247 """
1248 def test_type(self):
1249 """
1250 L{Error} is an exception type.
1251 """
1252 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05001253 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05001254
1255
1256
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001257class ConstantsTests(TestCase):
1258 """
1259 Tests for the values of constants exposed in L{OpenSSL.SSL}.
1260
1261 These are values defined by OpenSSL intended only to be used as flags to
1262 OpenSSL APIs. The only assertions it seems can be made about them is
1263 their values.
1264 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001265 # unittest.TestCase has no skip mechanism
1266 if OP_NO_QUERY_MTU is not None:
1267 def test_op_no_query_mtu(self):
1268 """
1269 The value of L{OpenSSL.SSL.OP_NO_QUERY_MTU} is 0x1000, the value of
1270 I{SSL_OP_NO_QUERY_MTU} defined by I{openssl/ssl.h}.
1271 """
1272 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
1273 else:
1274 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001275
1276
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001277 if OP_COOKIE_EXCHANGE is not None:
1278 def test_op_cookie_exchange(self):
1279 """
1280 The value of L{OpenSSL.SSL.OP_COOKIE_EXCHANGE} is 0x2000, the value
1281 of I{SSL_OP_COOKIE_EXCHANGE} defined by I{openssl/ssl.h}.
1282 """
1283 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
1284 else:
1285 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001286
1287
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001288 if OP_NO_TICKET is not None:
1289 def test_op_no_ticket(self):
1290 """
1291 The value of L{OpenSSL.SSL.OP_NO_TICKET} is 0x4000, the value of
1292 I{SSL_OP_NO_TICKET} defined by I{openssl/ssl.h}.
1293 """
1294 self.assertEqual(OP_NO_TICKET, 0x4000)
1295 else:
1296 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05001297
1298
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04001299
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001300class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05001301 """
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001302 Tests for L{OpenSSL.SSL.Connection} using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05001303 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001304 def _server(self, sock):
1305 """
1306 Create a new server-side SSL L{Connection} object wrapped around
1307 C{sock}.
1308 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001309 # Create the server side Connection. This is mostly setup boilerplate
1310 # - use TLSv1, use a particular certificate, etc.
1311 server_ctx = Context(TLSv1_METHOD)
1312 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1313 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1314 server_store = server_ctx.get_cert_store()
1315 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1316 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1317 server_ctx.check_privatekey()
1318 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001319 # Here the Connection is actually created. If None is passed as the 2nd
1320 # parameter, it indicates a memory BIO should be created.
1321 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001322 server_conn.set_accept_state()
1323 return server_conn
1324
1325
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001326 def _client(self, sock):
1327 """
1328 Create a new client-side SSL L{Connection} object wrapped around
1329 C{sock}.
1330 """
1331 # Now create the client side Connection. Similar boilerplate to the
1332 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001333 client_ctx = Context(TLSv1_METHOD)
1334 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1335 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1336 client_store = client_ctx.get_cert_store()
1337 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
1338 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
1339 client_ctx.check_privatekey()
1340 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001341 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001342 client_conn.set_connect_state()
1343 return client_conn
1344
1345
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001346 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001347 """
1348 Two L{Connection}s which use memory BIOs can be manually connected by
1349 reading from the output of each and writing those bytes to the input of
1350 the other and in this way establish a connection and exchange
1351 application-level bytes with each other.
1352 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001353 server_conn = self._server(None)
1354 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001355
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001356 # There should be no key or nonces yet.
1357 self.assertIdentical(server_conn.master_key(), None)
1358 self.assertIdentical(server_conn.client_random(), None)
1359 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001360
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001361 # First, the handshake needs to happen. We'll deliver bytes back and
1362 # forth between the client and server until neither of them feels like
1363 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001364 self.assertIdentical(
1365 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001366
1367 # Now that the handshake is done, there should be a key and nonces.
1368 self.assertNotIdentical(server_conn.master_key(), None)
1369 self.assertNotIdentical(server_conn.client_random(), None)
1370 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04001371 self.assertEquals(server_conn.client_random(), client_conn.client_random())
1372 self.assertEquals(server_conn.server_random(), client_conn.server_random())
1373 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
1374 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001375
1376 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04001377 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05001378
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001379 server_conn.write(important_message)
1380 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001381 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001382 (client_conn, important_message))
1383
1384 client_conn.write(important_message[::-1])
1385 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001386 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001387 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05001388
1389
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001390 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05001391 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001392 Just like L{test_memoryConnect} but with an actual socket.
1393
1394 This is primarily to rule out the memory BIO code as the source of
1395 any problems encountered while passing data over a L{Connection} (if
1396 this test fails, there must be a problem outside the memory BIO
1397 code, as no memory BIO is involved here). Even though this isn't a
1398 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05001399 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04001400 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05001401
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04001402 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05001403 client_conn.send(important_message)
1404 msg = server_conn.recv(1024)
1405 self.assertEqual(msg, important_message)
1406
1407 # Again in the other direction, just for fun.
1408 important_message = important_message[::-1]
1409 server_conn.send(important_message)
1410 msg = client_conn.recv(1024)
1411 self.assertEqual(msg, important_message)
1412
1413
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04001414 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05001415 """
1416 Test that L{OpenSSL.SSL.bio_read} and L{OpenSSL.SSL.bio_write} don't
1417 work on L{OpenSSL.SSL.Connection}() that use sockets.
1418 """
1419 context = Context(SSLv3_METHOD)
1420 client = socket()
1421 clientSSL = Connection(context, client)
1422 self.assertRaises( TypeError, clientSSL.bio_read, 100)
1423 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04001424 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001425
1426
1427 def test_outgoingOverflow(self):
1428 """
1429 If more bytes than can be written to the memory BIO are passed to
1430 L{Connection.send} at once, the number of bytes which were written is
1431 returned and that many bytes from the beginning of the input can be
1432 read from the other end of the connection.
1433 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001434 server = self._server(None)
1435 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001436
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001437 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001438
1439 size = 2 ** 15
1440 sent = client.send("x" * size)
1441 # Sanity check. We're trying to test what happens when the entire
1442 # input can't be sent. If the entire input was sent, this test is
1443 # meaningless.
1444 self.assertTrue(sent < size)
1445
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001446 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001447 self.assertIdentical(receiver, server)
1448
1449 # We can rely on all of these bytes being received at once because
1450 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
1451 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001452
1453
1454 def test_shutdown(self):
1455 """
1456 L{Connection.bio_shutdown} signals the end of the data stream from
1457 which the L{Connection} reads.
1458 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001459 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001460 server.bio_shutdown()
1461 e = self.assertRaises(Error, server.recv, 1024)
1462 # We don't want WantReadError or ZeroReturnError or anything - it's a
1463 # handshake failure.
1464 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001465
1466
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001467 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001468 """
1469 Verify the return value of the C{get_client_ca_list} method for server and client connections.
1470
1471 @param func: A function which will be called with the server context
1472 before the client and server are connected to each other. This
1473 function should specify a list of CAs for the server to send to the
1474 client and return that same list. The list will be used to verify
1475 that C{get_client_ca_list} returns the proper value at various
1476 times.
1477 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001478 server = self._server(None)
1479 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001480 self.assertEqual(client.get_client_ca_list(), [])
1481 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001482 ctx = server.get_context()
1483 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001484 self.assertEqual(client.get_client_ca_list(), [])
1485 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001486 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001487 self.assertEqual(client.get_client_ca_list(), expected)
1488 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001489
1490
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001491 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001492 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001493 L{Context.set_client_ca_list} raises a L{TypeError} if called with a
1494 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001495 """
1496 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001497 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
1498 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
1499 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001500
1501
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001502 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001503 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001504 If passed an empty list, L{Context.set_client_ca_list} configures the
1505 context to send no CA names to the client and, on both the server and
1506 client sides, L{Connection.get_client_ca_list} returns an empty list
1507 after the connection is set up.
1508 """
1509 def no_ca(ctx):
1510 ctx.set_client_ca_list([])
1511 return []
1512 self._check_client_ca_list(no_ca)
1513
1514
1515 def test_set_one_ca_list(self):
1516 """
1517 If passed a list containing a single X509Name,
1518 L{Context.set_client_ca_list} configures the context to send that CA
1519 name to the client and, on both the server and client sides,
1520 L{Connection.get_client_ca_list} returns a list containing that
1521 X509Name after the connection is set up.
1522 """
1523 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1524 cadesc = cacert.get_subject()
1525 def single_ca(ctx):
1526 ctx.set_client_ca_list([cadesc])
1527 return [cadesc]
1528 self._check_client_ca_list(single_ca)
1529
1530
1531 def test_set_multiple_ca_list(self):
1532 """
1533 If passed a list containing multiple X509Name objects,
1534 L{Context.set_client_ca_list} configures the context to send those CA
1535 names to the client and, on both the server and client sides,
1536 L{Connection.get_client_ca_list} returns a list containing those
1537 X509Names after the connection is set up.
1538 """
1539 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1540 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1541
1542 sedesc = secert.get_subject()
1543 cldesc = clcert.get_subject()
1544
1545 def multiple_ca(ctx):
1546 L = [sedesc, cldesc]
1547 ctx.set_client_ca_list(L)
1548 return L
1549 self._check_client_ca_list(multiple_ca)
1550
1551
1552 def test_reset_ca_list(self):
1553 """
1554 If called multiple times, only the X509Names passed to the final call
1555 of L{Context.set_client_ca_list} are used to configure the CA names
1556 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001557 """
1558 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1559 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1560 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1561
1562 cadesc = cacert.get_subject()
1563 sedesc = secert.get_subject()
1564 cldesc = clcert.get_subject()
1565
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001566 def changed_ca(ctx):
1567 ctx.set_client_ca_list([sedesc, cldesc])
1568 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001569 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001570 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001571
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001572
1573 def test_mutated_ca_list(self):
1574 """
1575 If the list passed to L{Context.set_client_ca_list} is mutated
1576 afterwards, this does not affect the list of CA names sent to the
1577 client.
1578 """
1579 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1580 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1581
1582 cadesc = cacert.get_subject()
1583 sedesc = secert.get_subject()
1584
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001585 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001586 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001587 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001588 L.append(sedesc)
1589 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001590 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001591
1592
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001593 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001594 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001595 L{Context.add_client_ca} raises L{TypeError} if called with a non-X509
1596 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001597 """
1598 ctx = Context(TLSv1_METHOD)
1599 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001600 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001601 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001602 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001603
1604
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001605 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001606 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001607 A certificate's subject can be added as a CA to be sent to the client
1608 with L{Context.add_client_ca}.
1609 """
1610 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1611 cadesc = cacert.get_subject()
1612 def single_ca(ctx):
1613 ctx.add_client_ca(cacert)
1614 return [cadesc]
1615 self._check_client_ca_list(single_ca)
1616
1617
1618 def test_multiple_add_client_ca(self):
1619 """
1620 Multiple CA names can be sent to the client by calling
1621 L{Context.add_client_ca} with multiple X509 objects.
1622 """
1623 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1624 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1625
1626 cadesc = cacert.get_subject()
1627 sedesc = secert.get_subject()
1628
1629 def multiple_ca(ctx):
1630 ctx.add_client_ca(cacert)
1631 ctx.add_client_ca(secert)
1632 return [cadesc, sedesc]
1633 self._check_client_ca_list(multiple_ca)
1634
1635
1636 def test_set_and_add_client_ca(self):
1637 """
1638 A call to L{Context.set_client_ca_list} followed by a call to
1639 L{Context.add_client_ca} results in using the CA names from the first
1640 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001641 """
1642 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1643 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1644 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1645
1646 cadesc = cacert.get_subject()
1647 sedesc = secert.get_subject()
1648 cldesc = clcert.get_subject()
1649
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001650 def mixed_set_add_ca(ctx):
1651 ctx.set_client_ca_list([cadesc, sedesc])
1652 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001653 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001654 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001655
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001656
1657 def test_set_after_add_client_ca(self):
1658 """
1659 A call to L{Context.set_client_ca_list} after a call to
1660 L{Context.add_client_ca} replaces the CA name specified by the former
1661 call with the names specified by the latter cal.
1662 """
1663 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1664 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1665 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1666
1667 cadesc = cacert.get_subject()
1668 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001669
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001670 def set_replaces_add_ca(ctx):
1671 ctx.add_client_ca(clcert)
1672 ctx.set_client_ca_list([cadesc])
1673 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001674 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001675 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001676
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001677
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001678
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001679if __name__ == '__main__':
1680 main()