blob: 5752d139349036e58169ea257e89fa2fbea4b359 [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
Jean-Paul Calderone95b92c72011-05-17 15:45:21 -0400310 def test_get_peer_cert_chain(self):
311 """
312 L{Connection.get_peer_cert_chain} returns the tuple of certificates
313 which the connected server returned for the certification verification.
314 """
315 # Testing this requires a server with a certificate signed by one of
316 # the CAs in the platform CA location. Getting one of those costs
317 # money. Fortunately (or unfortunately, depending on your
318 # perspective), it's easy to think of a public server on the
319 # internet which has such a certificate. Connecting to the network
320 # in a unit test is bad, but it's the only way I can think of to
321 # really test this. -exarkun
322
323 # Arg, verisign.com doesn't speak TLSv1
324 context = Context(SSLv3_METHOD)
325
326 client = socket()
327 client.connect(('verisign.com', 443))
328 clientSSL = Connection(context, client)
329 clientSSL.set_connect_state()
330 clientSSL.do_handshake()
331 cert = clientSSL.get_peer_certificate()
332 certs = clientSSL.get_peer_cert_chain()
333 self.assertEqual(dump_certificate(FILETYPE_PEM, cert),
334 dump_certificate(FILETYPE_PEM, certs[0]))
335 self.assertEqual(certs[0].get_subject().CN, 'www.verisign.com')
336 self.assertEqual(certs[1].get_subject().CN,
337 'VeriSign Class 3 Extended Validation SSL SGC CA')
338 self.assertEqual(certs[2].get_subject().CN,
339 'VeriSign Class 3 Public Primary Certification Authority - G5')
340
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400341
342 def test_timeout(self):
343 """
344 L{Context.set_timeout} sets the session timeout for all connections
345 created using the context object. L{Context.get_timeout} retrieves this
346 value.
347 """
348 context = Context(TLSv1_METHOD)
349 context.set_timeout(1234)
350 self.assertEquals(context.get_timeout(), 1234)
351
352
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400353 def test_set_verify_depth_wrong_args(self):
354 """
355 L{Context.set_verify_depth} raises L{TypeError} if called with the wrong
356 number of arguments or a non-C{int} argument.
357 """
358 context = Context(TLSv1_METHOD)
359 self.assertRaises(TypeError, context.set_verify_depth)
360 self.assertRaises(TypeError, context.set_verify_depth, None)
361 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
362
363
364 def test_get_verify_depth_wrong_args(self):
365 """
366 L{Context.get_verify_depth} raises L{TypeError} if called with any arguments.
367 """
368 context = Context(TLSv1_METHOD)
369 self.assertRaises(TypeError, context.get_verify_depth, None)
370
371
372 def test_verify_depth(self):
373 """
374 L{Context.set_verify_depth} sets the number of certificates in a chain
375 to follow before giving up. The value can be retrieved with
376 L{Context.get_verify_depth}.
377 """
378 context = Context(TLSv1_METHOD)
379 context.set_verify_depth(11)
380 self.assertEquals(context.get_verify_depth(), 11)
381
382
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400383 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400384 """
385 Write a new private key out to a new file, encrypted using the given
386 passphrase. Return the path to the new file.
387 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400388 key = PKey()
389 key.generate_key(TYPE_RSA, 128)
390 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400391 fObj = open(pemFile, 'w')
392 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
393 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400394 fObj.close()
395 return pemFile
396
397
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400398 def test_set_passwd_cb_wrong_args(self):
399 """
400 L{Context.set_passwd_cb} raises L{TypeError} if called with the
401 wrong arguments or with a non-callable first argument.
402 """
403 context = Context(TLSv1_METHOD)
404 self.assertRaises(TypeError, context.set_passwd_cb)
405 self.assertRaises(TypeError, context.set_passwd_cb, None)
406 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
407
408
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400409 def test_set_passwd_cb(self):
410 """
411 L{Context.set_passwd_cb} accepts a callable which will be invoked when
412 a private key is loaded from an encrypted PEM.
413 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400414 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400415 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400416 calledWith = []
417 def passphraseCallback(maxlen, verify, extra):
418 calledWith.append((maxlen, verify, extra))
419 return passphrase
420 context = Context(TLSv1_METHOD)
421 context.set_passwd_cb(passphraseCallback)
422 context.use_privatekey_file(pemFile)
423 self.assertTrue(len(calledWith), 1)
424 self.assertTrue(isinstance(calledWith[0][0], int))
425 self.assertTrue(isinstance(calledWith[0][1], int))
426 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400427
428
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400429 def test_passwd_callback_exception(self):
430 """
431 L{Context.use_privatekey_file} propagates any exception raised by the
432 passphrase callback.
433 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400434 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400435 def passphraseCallback(maxlen, verify, extra):
436 raise RuntimeError("Sorry, I am a fail.")
437
438 context = Context(TLSv1_METHOD)
439 context.set_passwd_cb(passphraseCallback)
440 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
441
442
443 def test_passwd_callback_false(self):
444 """
445 L{Context.use_privatekey_file} raises L{OpenSSL.SSL.Error} if the
446 passphrase callback returns a false value.
447 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400448 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400449 def passphraseCallback(maxlen, verify, extra):
450 return None
451
452 context = Context(TLSv1_METHOD)
453 context.set_passwd_cb(passphraseCallback)
454 self.assertRaises(Error, context.use_privatekey_file, pemFile)
455
456
457 def test_passwd_callback_non_string(self):
458 """
459 L{Context.use_privatekey_file} raises L{OpenSSL.SSL.Error} if the
460 passphrase callback returns a true non-string value.
461 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400462 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400463 def passphraseCallback(maxlen, verify, extra):
464 return 10
465
466 context = Context(TLSv1_METHOD)
467 context.set_passwd_cb(passphraseCallback)
468 self.assertRaises(Error, context.use_privatekey_file, pemFile)
469
470
471 def test_passwd_callback_too_long(self):
472 """
473 If the passphrase returned by the passphrase callback returns a string
474 longer than the indicated maximum length, it is truncated.
475 """
476 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400477 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400478 pemFile = self._write_encrypted_pem(passphrase)
479 def passphraseCallback(maxlen, verify, extra):
480 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400481 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400482
483 context = Context(TLSv1_METHOD)
484 context.set_passwd_cb(passphraseCallback)
485 # This shall succeed because the truncated result is the correct
486 # passphrase.
487 context.use_privatekey_file(pemFile)
488
489
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400490 def test_set_info_callback(self):
491 """
492 L{Context.set_info_callback} accepts a callable which will be invoked
493 when certain information about an SSL connection is available.
494 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500495 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400496
497 clientSSL = Connection(Context(TLSv1_METHOD), client)
498 clientSSL.set_connect_state()
499
500 called = []
501 def info(conn, where, ret):
502 called.append((conn, where, ret))
503 context = Context(TLSv1_METHOD)
504 context.set_info_callback(info)
505 context.use_certificate(
506 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
507 context.use_privatekey(
508 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
509
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400510 serverSSL = Connection(context, server)
511 serverSSL.set_accept_state()
512
513 while not called:
514 for ssl in clientSSL, serverSSL:
515 try:
516 ssl.do_handshake()
517 except WantReadError:
518 pass
519
520 # Kind of lame. Just make sure it got called somehow.
521 self.assertTrue(called)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400522
523
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400524 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400525 """
526 Create a client context which will verify the peer certificate and call
527 its C{load_verify_locations} method with C{*args}. Then connect it to a
528 server and ensure that the handshake succeeds.
529 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500530 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400531
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400532 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400533 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400534 # Require that the server certificate verify properly or the
535 # connection will fail.
536 clientContext.set_verify(
537 VERIFY_PEER,
538 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
539
540 clientSSL = Connection(clientContext, client)
541 clientSSL.set_connect_state()
542
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400543 serverContext = Context(TLSv1_METHOD)
544 serverContext.use_certificate(
545 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
546 serverContext.use_privatekey(
547 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
548
549 serverSSL = Connection(serverContext, server)
550 serverSSL.set_accept_state()
551
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400552 # Without load_verify_locations above, the handshake
553 # will fail:
554 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
555 # 'certificate verify failed')]
556 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400557
558 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400559 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400560
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500561
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400562 def test_load_verify_file(self):
563 """
564 L{Context.load_verify_locations} accepts a file name and uses the
565 certificates within for verification purposes.
566 """
567 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400568 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400569 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400570 fObj.close()
571
572 self._load_verify_locations_test(cafile)
573
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400574
575 def test_load_verify_invalid_file(self):
576 """
577 L{Context.load_verify_locations} raises L{Error} when passed a
578 non-existent cafile.
579 """
580 clientContext = Context(TLSv1_METHOD)
581 self.assertRaises(
582 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400583
584
585 def test_load_verify_directory(self):
586 """
587 L{Context.load_verify_locations} accepts a directory name and uses
588 the certificates within for verification purposes.
589 """
590 capath = self.mktemp()
591 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400592 # Hash values computed manually with c_rehash to avoid depending on
593 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
594 # from OpenSSL 1.0.0.
595 for name in ['c7adac82.0', 'c3705638.0']:
596 cafile = join(capath, name)
597 fObj = open(cafile, 'w')
598 fObj.write(cleartextCertificatePEM.decode('ascii'))
599 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400600
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400601 self._load_verify_locations_test(None, capath)
602
603
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400604 def test_load_verify_locations_wrong_args(self):
605 """
606 L{Context.load_verify_locations} raises L{TypeError} if called with
607 the wrong number of arguments or with non-C{str} arguments.
608 """
609 context = Context(TLSv1_METHOD)
610 self.assertRaises(TypeError, context.load_verify_locations)
611 self.assertRaises(TypeError, context.load_verify_locations, object())
612 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
613 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
614
615
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400616 if platform == "win32":
617 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400618 "See LP#404343 and LP#404344."
619 else:
620 def test_set_default_verify_paths(self):
621 """
622 L{Context.set_default_verify_paths} causes the platform-specific CA
623 certificate locations to be used for verification purposes.
624 """
625 # Testing this requires a server with a certificate signed by one of
626 # the CAs in the platform CA location. Getting one of those costs
627 # money. Fortunately (or unfortunately, depending on your
628 # perspective), it's easy to think of a public server on the
629 # internet which has such a certificate. Connecting to the network
630 # in a unit test is bad, but it's the only way I can think of to
631 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400632
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400633 # Arg, verisign.com doesn't speak TLSv1
634 context = Context(SSLv3_METHOD)
635 context.set_default_verify_paths()
636 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200637 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400638 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400639
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400640 client = socket()
641 client.connect(('verisign.com', 443))
642 clientSSL = Connection(context, client)
643 clientSSL.set_connect_state()
644 clientSSL.do_handshake()
645 clientSSL.send('GET / HTTP/1.0\r\n\r\n')
646 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400647
648
649 def test_set_default_verify_paths_signature(self):
650 """
651 L{Context.set_default_verify_paths} takes no arguments and raises
652 L{TypeError} if given any.
653 """
654 context = Context(TLSv1_METHOD)
655 self.assertRaises(TypeError, context.set_default_verify_paths, None)
656 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
657 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500658
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400659
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500660 def test_add_extra_chain_cert_invalid_cert(self):
661 """
662 L{Context.add_extra_chain_cert} raises L{TypeError} if called with
663 other than one argument or if called with an object which is not an
664 instance of L{X509}.
665 """
666 context = Context(TLSv1_METHOD)
667 self.assertRaises(TypeError, context.add_extra_chain_cert)
668 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
669 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
670
671
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400672 def _create_certificate_chain(self):
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500673 """
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400674 Construct and return a chain of certificates.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400675
676 1. A new self-signed certificate authority certificate (cacert)
677 2. A new intermediate certificate signed by cacert (icert)
678 3. A new server certificate signed by icert (scert)
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500679 """
Jean-Paul Calderone9b0744c2010-09-14 18:11:01 -0400680 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500681
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400682 # Step 1
683 cakey = PKey()
684 cakey.generate_key(TYPE_RSA, 512)
685 cacert = X509()
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400686 cacert.get_subject().commonName = "Authority Certificate"
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400687 cacert.set_issuer(cacert.get_subject())
688 cacert.set_pubkey(cakey)
Jean-Paul Calderone4e6aed62010-09-19 10:05:34 -0400689 cacert.set_notBefore(b("20000101000000Z"))
690 cacert.set_notAfter(b("20200101000000Z"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400691 cacert.add_extensions([caext])
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400692 cacert.set_serial_number(0)
693 cacert.sign(cakey, "sha1")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500694
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400695 # Step 2
696 ikey = PKey()
697 ikey.generate_key(TYPE_RSA, 512)
698 icert = X509()
699 icert.get_subject().commonName = "Intermediate Certificate"
700 icert.set_issuer(cacert.get_subject())
701 icert.set_pubkey(ikey)
Jean-Paul Calderone4e6aed62010-09-19 10:05:34 -0400702 icert.set_notBefore(b("20000101000000Z"))
703 icert.set_notAfter(b("20200101000000Z"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400704 icert.add_extensions([caext])
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400705 icert.set_serial_number(0)
706 icert.sign(cakey, "sha1")
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400707
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400708 # Step 3
709 skey = PKey()
710 skey.generate_key(TYPE_RSA, 512)
711 scert = X509()
712 scert.get_subject().commonName = "Server Certificate"
713 scert.set_issuer(icert.get_subject())
714 scert.set_pubkey(skey)
Jean-Paul Calderone4e6aed62010-09-19 10:05:34 -0400715 scert.set_notBefore(b("20000101000000Z"))
716 scert.set_notAfter(b("20200101000000Z"))
Jean-Paul Calderone2db1de52010-09-19 10:08:13 -0400717 scert.add_extensions([
718 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400719 scert.set_serial_number(0)
720 scert.sign(ikey, "sha1")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400721
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400722 return [(cakey, cacert), (ikey, icert), (skey, scert)]
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400723
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400724
725 def _handshake_test(self, serverContext, clientContext):
726 """
727 Verify that a client and server created with the given contexts can
728 successfully handshake and communicate.
729 """
730 serverSocket, clientSocket = socket_pair()
731
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400732 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400733 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400734
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400735 client = Connection(clientContext, clientSocket)
736 client.set_connect_state()
737
738 # Make them talk to each other.
739 # self._interactInMemory(client, server)
740 for i in range(3):
741 for s in [client, server]:
742 try:
743 s.do_handshake()
744 except WantReadError:
745 pass
746
747
748 def test_add_extra_chain_cert(self):
749 """
750 L{Context.add_extra_chain_cert} accepts an L{X509} instance to add to
751 the certificate chain.
752
753 See L{_create_certificate_chain} for the details of the certificate
754 chain tested.
755
756 The chain is tested by starting a server with scert and connecting
757 to it with a client which trusts cacert and requires verification to
758 succeed.
759 """
760 chain = self._create_certificate_chain()
761 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
762
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400763 # Dump the CA certificate to a file because that's the only way to load
764 # it as a trusted CA in the client context.
765 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400766 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400767 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400768 fObj.close()
769
770 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400771 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400772 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400773 fObj.close()
774
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400775 # Create the server context
776 serverContext = Context(TLSv1_METHOD)
777 serverContext.use_privatekey(skey)
778 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400779 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400780 serverContext.add_extra_chain_cert(icert)
781
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400782 # Create the client
783 clientContext = Context(TLSv1_METHOD)
784 clientContext.set_verify(
785 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
786 clientContext.load_verify_locations('ca.pem')
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400787
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400788 # Try it out.
789 self._handshake_test(serverContext, clientContext)
790
791
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400792 def test_use_certificate_chain_file(self):
793 """
794 L{Context.use_certificate_chain_file} reads a certificate chain from
795 the specified file.
796
797 The chain is tested by starting a server with scert and connecting
798 to it with a client which trusts cacert and requires verification to
799 succeed.
800 """
801 chain = self._create_certificate_chain()
802 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
803
804 # Write out the chain file.
805 chainFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400806 fObj = open(chainFile, 'w')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400807 # Most specific to least general.
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400808 fObj.write(dump_certificate(FILETYPE_PEM, scert).decode('ascii'))
809 fObj.write(dump_certificate(FILETYPE_PEM, icert).decode('ascii'))
810 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400811 fObj.close()
812
813 serverContext = Context(TLSv1_METHOD)
814 serverContext.use_certificate_chain_file(chainFile)
815 serverContext.use_privatekey(skey)
816
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400817 fObj = open('ca.pem', 'w')
818 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400819 fObj.close()
820
821 clientContext = Context(TLSv1_METHOD)
822 clientContext.set_verify(
823 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
824 clientContext.load_verify_locations('ca.pem')
825
826 self._handshake_test(serverContext, clientContext)
827
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -0400828 # XXX load_client_ca
829 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -0400830
831 def test_get_verify_mode_wrong_args(self):
832 """
833 L{Context.get_verify_mode} raises L{TypeError} if called with any
834 arguments.
835 """
836 context = Context(TLSv1_METHOD)
837 self.assertRaises(TypeError, context.get_verify_mode, None)
838
839
840 def test_get_verify_mode(self):
841 """
842 L{Context.get_verify_mode} returns the verify mode flags previously
843 passed to L{Context.set_verify}.
844 """
845 context = Context(TLSv1_METHOD)
846 self.assertEquals(context.get_verify_mode(), 0)
847 context.set_verify(
848 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
849 self.assertEquals(
850 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
851
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400852
853 def test_load_tmp_dh_wrong_args(self):
854 """
855 L{Context.load_tmp_dh} raises L{TypeError} if called with the wrong
856 number of arguments or with a non-C{str} argument.
857 """
858 context = Context(TLSv1_METHOD)
859 self.assertRaises(TypeError, context.load_tmp_dh)
860 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
861 self.assertRaises(TypeError, context.load_tmp_dh, object())
862
863
864 def test_load_tmp_dh_missing_file(self):
865 """
866 L{Context.load_tmp_dh} raises L{OpenSSL.SSL.Error} if the specified file
867 does not exist.
868 """
869 context = Context(TLSv1_METHOD)
870 self.assertRaises(Error, context.load_tmp_dh, "hello")
871
872
873 def test_load_tmp_dh(self):
874 """
875 L{Context.load_tmp_dh} loads Diffie-Hellman parameters from the
876 specified file.
877 """
878 context = Context(TLSv1_METHOD)
879 dhfilename = self.mktemp()
880 dhfile = open(dhfilename, "w")
881 dhfile.write(dhparam)
882 dhfile.close()
883 context.load_tmp_dh(dhfilename)
884 # XXX What should I assert here? -exarkun
885
886
887 def test_set_cipher_list(self):
888 """
889 L{Context.set_cipher_list} accepts a C{str} naming the ciphers which
890 connections created with the context object will be able to choose from.
891 """
892 context = Context(TLSv1_METHOD)
893 context.set_cipher_list("hello world:EXP-RC4-MD5")
894 conn = Connection(context, None)
895 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400896
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400897
898
899class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -0500900 """
901 Unit tests for L{OpenSSL.SSL.Connection}.
902 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -0400903 # XXX want_write
904 # XXX want_read
905 # XXX get_peer_certificate -> None
906 # XXX sock_shutdown
907 # XXX master_key -> TypeError
908 # XXX server_random -> TypeError
909 # XXX state_string
910 # XXX connect -> TypeError
911 # XXX connect_ex -> TypeError
912 # XXX set_connect_state -> TypeError
913 # XXX set_accept_state -> TypeError
914 # XXX renegotiate_pending
915 # XXX do_handshake -> TypeError
916 # XXX bio_read -> TypeError
917 # XXX recv -> TypeError
918 # XXX send -> TypeError
919 # XXX bio_write -> TypeError
920
Rick Deane15b1472009-07-09 15:53:42 -0500921 def test_type(self):
922 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400923 L{Connection} and L{ConnectionType} refer to the same type object and
924 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500925 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400926 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -0500927 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400928 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -0500929
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400930
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -0500931 def test_get_context(self):
932 """
933 L{Connection.get_context} returns the L{Context} instance used to
934 construct the L{Connection} instance.
935 """
936 context = Context(TLSv1_METHOD)
937 connection = Connection(context, None)
938 self.assertIdentical(connection.get_context(), context)
939
940
941 def test_get_context_wrong_args(self):
942 """
943 L{Connection.get_context} raises L{TypeError} if called with any
944 arguments.
945 """
946 connection = Connection(Context(TLSv1_METHOD), None)
947 self.assertRaises(TypeError, connection.get_context, None)
948
949
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -0400950 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400951 """
952 L{Connection.pending} returns the number of bytes available for
953 immediate read.
954 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -0400955 connection = Connection(Context(TLSv1_METHOD), None)
956 self.assertEquals(connection.pending(), 0)
957
958
959 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400960 """
961 L{Connection.pending} raises L{TypeError} if called with any arguments.
962 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -0400963 connection = Connection(Context(TLSv1_METHOD), None)
964 self.assertRaises(TypeError, connection.pending, None)
965
966
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400967 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400968 """
969 L{Connection.connect} raises L{TypeError} if called with a non-address
970 argument or with the wrong number of arguments.
971 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400972 connection = Connection(Context(TLSv1_METHOD), socket())
973 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400974 self.assertRaises(TypeError, connection.connect)
975 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400976
977
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400978 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400979 """
980 L{Connection.connect} raises L{socket.error} if the underlying socket
981 connect method raises it.
982 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400983 client = socket()
984 context = Context(TLSv1_METHOD)
985 clientSSL = Connection(context, client)
986 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -0400987 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400988
989
990 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400991 """
992 L{Connection.connect} establishes a connection to the specified address.
993 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400994 port = socket()
995 port.bind(('', 0))
996 port.listen(3)
997
998 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -0400999 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1000 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001001
1002
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001003 if platform == "darwin":
1004 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1005 else:
1006 def test_connect_ex(self):
1007 """
1008 If there is a connection error, L{Connection.connect_ex} returns the
1009 errno instead of raising an exception.
1010 """
1011 port = socket()
1012 port.bind(('', 0))
1013 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001014
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001015 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1016 clientSSL.setblocking(False)
1017 result = clientSSL.connect_ex(port.getsockname())
1018 expected = (EINPROGRESS, EWOULDBLOCK)
1019 self.assertTrue(
1020 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001021
1022
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001023 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001024 """
1025 L{Connection.accept} raises L{TypeError} if called with any arguments.
1026 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001027 connection = Connection(Context(TLSv1_METHOD), socket())
1028 self.assertRaises(TypeError, connection.accept, None)
1029
1030
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001031 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001032 """
1033 L{Connection.accept} accepts a pending connection attempt and returns a
1034 tuple of a new L{Connection} (the accepted client) and the address the
1035 connection originated from.
1036 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001037 ctx = Context(TLSv1_METHOD)
1038 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1039 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001040 port = socket()
1041 portSSL = Connection(ctx, port)
1042 portSSL.bind(('', 0))
1043 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001044
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001045 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001046
1047 # Calling portSSL.getsockname() here to get the server IP address sounds
1048 # great, but frequently fails on Windows.
1049 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001050
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001051 serverSSL, address = portSSL.accept()
1052
1053 self.assertTrue(isinstance(serverSSL, Connection))
1054 self.assertIdentical(serverSSL.get_context(), ctx)
1055 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001056
1057
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001058 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001059 """
1060 L{Connection.shutdown} raises L{TypeError} if called with the wrong
1061 number of arguments or with arguments other than integers.
1062 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001063 connection = Connection(Context(TLSv1_METHOD), None)
1064 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001065 self.assertRaises(TypeError, connection.get_shutdown, None)
1066 self.assertRaises(TypeError, connection.set_shutdown)
1067 self.assertRaises(TypeError, connection.set_shutdown, None)
1068 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001069
1070
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001071 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001072 """
1073 L{Connection.shutdown} performs an SSL-level connection shutdown.
1074 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001075 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001076 self.assertFalse(server.shutdown())
1077 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001078 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001079 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1080 client.shutdown()
1081 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1082 self.assertRaises(ZeroReturnError, server.recv, 1024)
1083 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001084
1085
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001086 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001087 """
1088 L{Connection.set_shutdown} sets the state of the SSL connection shutdown
1089 process.
1090 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001091 connection = Connection(Context(TLSv1_METHOD), socket())
1092 connection.set_shutdown(RECEIVED_SHUTDOWN)
1093 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1094
1095
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001096 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001097 """
1098 L{Connection.set_app_data} raises L{TypeError} if called with other than
1099 one argument. L{Connection.get_app_data} raises L{TypeError} if called
1100 with any arguments.
1101 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001102 conn = Connection(Context(TLSv1_METHOD), None)
1103 self.assertRaises(TypeError, conn.get_app_data, None)
1104 self.assertRaises(TypeError, conn.set_app_data)
1105 self.assertRaises(TypeError, conn.set_app_data, None, None)
1106
1107
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001108 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001109 """
1110 Any object can be set as app data by passing it to
1111 L{Connection.set_app_data} and later retrieved with
1112 L{Connection.get_app_data}.
1113 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001114 conn = Connection(Context(TLSv1_METHOD), None)
1115 app_data = object()
1116 conn.set_app_data(app_data)
1117 self.assertIdentical(conn.get_app_data(), app_data)
1118
1119
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001120 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001121 """
1122 L{Connection.makefile} is not implemented and calling that method raises
1123 L{NotImplementedError}.
1124 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001125 conn = Connection(Context(TLSv1_METHOD), None)
1126 self.assertRaises(NotImplementedError, conn.makefile)
1127
1128
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001129
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001130class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001131 """
1132 Tests for L{Connection.get_cipher_list}.
1133 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04001134 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001135 """
1136 L{Connection.get_cipher_list} raises L{TypeError} if called with any
1137 arguments.
1138 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001139 connection = Connection(Context(TLSv1_METHOD), None)
1140 self.assertRaises(TypeError, connection.get_cipher_list, None)
1141
1142
1143 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001144 """
1145 L{Connection.get_cipher_list} returns a C{list} of C{str} giving the
1146 names of the ciphers which might be used.
1147 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001148 connection = Connection(Context(TLSv1_METHOD), None)
1149 ciphers = connection.get_cipher_list()
1150 self.assertTrue(isinstance(ciphers, list))
1151 for cipher in ciphers:
1152 self.assertTrue(isinstance(cipher, str))
1153
1154
1155
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001156class ConnectionSendTests(TestCase, _LoopbackMixin):
1157 """
1158 Tests for L{Connection.send}
1159 """
1160 def test_wrong_args(self):
1161 """
1162 When called with arguments other than a single string,
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05001163 L{Connection.send} raises L{TypeError}.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001164 """
1165 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05001166 self.assertRaises(TypeError, connection.send)
1167 self.assertRaises(TypeError, connection.send, object())
1168 self.assertRaises(TypeError, connection.send, "foo", "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001169
1170
1171 def test_short_bytes(self):
1172 """
1173 When passed a short byte string, L{Connection.send} transmits all of it
1174 and returns the number of bytes sent.
1175 """
1176 server, client = self._loopback()
1177 count = server.send(b('xy'))
1178 self.assertEquals(count, 2)
1179 self.assertEquals(client.recv(2), b('xy'))
1180
1181 try:
1182 memoryview
1183 except NameError:
1184 "cannot test sending memoryview without memoryview"
1185 else:
1186 def test_short_memoryview(self):
1187 """
1188 When passed a memoryview onto a small number of bytes,
1189 L{Connection.send} transmits all of them and returns the number of
1190 bytes sent.
1191 """
1192 server, client = self._loopback()
1193 count = server.send(memoryview(b('xy')))
1194 self.assertEquals(count, 2)
1195 self.assertEquals(client.recv(2), b('xy'))
1196
1197
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001198
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001199class ConnectionSendallTests(TestCase, _LoopbackMixin):
1200 """
1201 Tests for L{Connection.sendall}.
1202 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001203 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001204 """
1205 When called with arguments other than a single string,
1206 L{Connection.sendall} raises L{TypeError}.
1207 """
1208 connection = Connection(Context(TLSv1_METHOD), None)
1209 self.assertRaises(TypeError, connection.sendall)
1210 self.assertRaises(TypeError, connection.sendall, object())
1211 self.assertRaises(TypeError, connection.sendall, "foo", "bar")
1212
1213
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001214 def test_short(self):
1215 """
1216 L{Connection.sendall} transmits all of the bytes in the string passed to
1217 it.
1218 """
1219 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001220 server.sendall(b('x'))
1221 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001222
1223
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001224 try:
1225 memoryview
1226 except NameError:
1227 "cannot test sending memoryview without memoryview"
1228 else:
1229 def test_short_memoryview(self):
1230 """
1231 When passed a memoryview onto a small number of bytes,
1232 L{Connection.sendall} transmits all of them.
1233 """
1234 server, client = self._loopback()
1235 server.sendall(memoryview(b('x')))
1236 self.assertEquals(client.recv(1), b('x'))
1237
1238
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001239 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001240 """
1241 L{Connection.sendall} transmits all of the bytes in the string passed to
1242 it even if this requires multiple calls of an underlying write function.
1243 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001244 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04001245 # Should be enough, underlying SSL_write should only do 16k at a time.
1246 # On Windows, after 32k of bytes the write will block (forever - because
1247 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04001248 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001249 server.sendall(message)
1250 accum = []
1251 received = 0
1252 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001253 data = client.recv(1024)
1254 accum.append(data)
1255 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04001256 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001257
1258
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001259 def test_closed(self):
1260 """
1261 If the underlying socket is closed, L{Connection.sendall} propagates the
1262 write error from the low level write call.
1263 """
1264 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04001265 server.sock_shutdown(2)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001266 self.assertRaises(SysCallError, server.sendall, "hello, world")
1267
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001268
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001269
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001270class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
1271 """
1272 Tests for SSL renegotiation APIs.
1273 """
1274 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001275 """
1276 L{Connection.renegotiate} raises L{TypeError} if called with any
1277 arguments.
1278 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001279 connection = Connection(Context(TLSv1_METHOD), None)
1280 self.assertRaises(TypeError, connection.renegotiate, None)
1281
1282
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001283 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001284 """
1285 L{Connection.total_renegotiations} raises L{TypeError} if called with
1286 any arguments.
1287 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001288 connection = Connection(Context(TLSv1_METHOD), None)
1289 self.assertRaises(TypeError, connection.total_renegotiations, None)
1290
1291
1292 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001293 """
1294 L{Connection.total_renegotiations} returns C{0} before any
1295 renegotiations have happened.
1296 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001297 connection = Connection(Context(TLSv1_METHOD), None)
1298 self.assertEquals(connection.total_renegotiations(), 0)
1299
1300
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001301# def test_renegotiate(self):
1302# """
1303# """
1304# server, client = self._loopback()
1305
1306# server.send("hello world")
1307# self.assertEquals(client.recv(len("hello world")), "hello world")
1308
1309# self.assertEquals(server.total_renegotiations(), 0)
1310# self.assertTrue(server.renegotiate())
1311
1312# server.setblocking(False)
1313# client.setblocking(False)
1314# while server.renegotiate_pending():
1315# client.do_handshake()
1316# server.do_handshake()
1317
1318# self.assertEquals(server.total_renegotiations(), 1)
1319
1320
1321
1322
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001323class ErrorTests(TestCase):
1324 """
1325 Unit tests for L{OpenSSL.SSL.Error}.
1326 """
1327 def test_type(self):
1328 """
1329 L{Error} is an exception type.
1330 """
1331 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05001332 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05001333
1334
1335
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001336class ConstantsTests(TestCase):
1337 """
1338 Tests for the values of constants exposed in L{OpenSSL.SSL}.
1339
1340 These are values defined by OpenSSL intended only to be used as flags to
1341 OpenSSL APIs. The only assertions it seems can be made about them is
1342 their values.
1343 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001344 # unittest.TestCase has no skip mechanism
1345 if OP_NO_QUERY_MTU is not None:
1346 def test_op_no_query_mtu(self):
1347 """
1348 The value of L{OpenSSL.SSL.OP_NO_QUERY_MTU} is 0x1000, the value of
1349 I{SSL_OP_NO_QUERY_MTU} defined by I{openssl/ssl.h}.
1350 """
1351 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
1352 else:
1353 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001354
1355
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001356 if OP_COOKIE_EXCHANGE is not None:
1357 def test_op_cookie_exchange(self):
1358 """
1359 The value of L{OpenSSL.SSL.OP_COOKIE_EXCHANGE} is 0x2000, the value
1360 of I{SSL_OP_COOKIE_EXCHANGE} defined by I{openssl/ssl.h}.
1361 """
1362 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
1363 else:
1364 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001365
1366
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001367 if OP_NO_TICKET is not None:
1368 def test_op_no_ticket(self):
1369 """
1370 The value of L{OpenSSL.SSL.OP_NO_TICKET} is 0x4000, the value of
1371 I{SSL_OP_NO_TICKET} defined by I{openssl/ssl.h}.
1372 """
1373 self.assertEqual(OP_NO_TICKET, 0x4000)
1374 else:
1375 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05001376
1377
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04001378
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001379class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05001380 """
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001381 Tests for L{OpenSSL.SSL.Connection} using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05001382 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001383 def _server(self, sock):
1384 """
1385 Create a new server-side SSL L{Connection} object wrapped around
1386 C{sock}.
1387 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001388 # Create the server side Connection. This is mostly setup boilerplate
1389 # - use TLSv1, use a particular certificate, etc.
1390 server_ctx = Context(TLSv1_METHOD)
1391 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1392 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1393 server_store = server_ctx.get_cert_store()
1394 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1395 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1396 server_ctx.check_privatekey()
1397 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001398 # Here the Connection is actually created. If None is passed as the 2nd
1399 # parameter, it indicates a memory BIO should be created.
1400 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001401 server_conn.set_accept_state()
1402 return server_conn
1403
1404
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001405 def _client(self, sock):
1406 """
1407 Create a new client-side SSL L{Connection} object wrapped around
1408 C{sock}.
1409 """
1410 # Now create the client side Connection. Similar boilerplate to the
1411 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001412 client_ctx = Context(TLSv1_METHOD)
1413 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1414 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1415 client_store = client_ctx.get_cert_store()
1416 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
1417 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
1418 client_ctx.check_privatekey()
1419 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001420 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001421 client_conn.set_connect_state()
1422 return client_conn
1423
1424
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001425 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001426 """
1427 Two L{Connection}s which use memory BIOs can be manually connected by
1428 reading from the output of each and writing those bytes to the input of
1429 the other and in this way establish a connection and exchange
1430 application-level bytes with each other.
1431 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001432 server_conn = self._server(None)
1433 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001434
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001435 # There should be no key or nonces yet.
1436 self.assertIdentical(server_conn.master_key(), None)
1437 self.assertIdentical(server_conn.client_random(), None)
1438 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001439
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001440 # First, the handshake needs to happen. We'll deliver bytes back and
1441 # forth between the client and server until neither of them feels like
1442 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001443 self.assertIdentical(
1444 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001445
1446 # Now that the handshake is done, there should be a key and nonces.
1447 self.assertNotIdentical(server_conn.master_key(), None)
1448 self.assertNotIdentical(server_conn.client_random(), None)
1449 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04001450 self.assertEquals(server_conn.client_random(), client_conn.client_random())
1451 self.assertEquals(server_conn.server_random(), client_conn.server_random())
1452 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
1453 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001454
1455 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04001456 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05001457
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001458 server_conn.write(important_message)
1459 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001460 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001461 (client_conn, important_message))
1462
1463 client_conn.write(important_message[::-1])
1464 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001465 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001466 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05001467
1468
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001469 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05001470 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001471 Just like L{test_memoryConnect} but with an actual socket.
1472
1473 This is primarily to rule out the memory BIO code as the source of
1474 any problems encountered while passing data over a L{Connection} (if
1475 this test fails, there must be a problem outside the memory BIO
1476 code, as no memory BIO is involved here). Even though this isn't a
1477 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05001478 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04001479 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05001480
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04001481 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05001482 client_conn.send(important_message)
1483 msg = server_conn.recv(1024)
1484 self.assertEqual(msg, important_message)
1485
1486 # Again in the other direction, just for fun.
1487 important_message = important_message[::-1]
1488 server_conn.send(important_message)
1489 msg = client_conn.recv(1024)
1490 self.assertEqual(msg, important_message)
1491
1492
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04001493 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05001494 """
1495 Test that L{OpenSSL.SSL.bio_read} and L{OpenSSL.SSL.bio_write} don't
1496 work on L{OpenSSL.SSL.Connection}() that use sockets.
1497 """
1498 context = Context(SSLv3_METHOD)
1499 client = socket()
1500 clientSSL = Connection(context, client)
1501 self.assertRaises( TypeError, clientSSL.bio_read, 100)
1502 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04001503 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001504
1505
1506 def test_outgoingOverflow(self):
1507 """
1508 If more bytes than can be written to the memory BIO are passed to
1509 L{Connection.send} at once, the number of bytes which were written is
1510 returned and that many bytes from the beginning of the input can be
1511 read from the other end of the connection.
1512 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001513 server = self._server(None)
1514 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001515
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001516 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001517
1518 size = 2 ** 15
1519 sent = client.send("x" * size)
1520 # Sanity check. We're trying to test what happens when the entire
1521 # input can't be sent. If the entire input was sent, this test is
1522 # meaningless.
1523 self.assertTrue(sent < size)
1524
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001525 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001526 self.assertIdentical(receiver, server)
1527
1528 # We can rely on all of these bytes being received at once because
1529 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
1530 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001531
1532
1533 def test_shutdown(self):
1534 """
1535 L{Connection.bio_shutdown} signals the end of the data stream from
1536 which the L{Connection} reads.
1537 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001538 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001539 server.bio_shutdown()
1540 e = self.assertRaises(Error, server.recv, 1024)
1541 # We don't want WantReadError or ZeroReturnError or anything - it's a
1542 # handshake failure.
1543 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001544
1545
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001546 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001547 """
1548 Verify the return value of the C{get_client_ca_list} method for server and client connections.
1549
1550 @param func: A function which will be called with the server context
1551 before the client and server are connected to each other. This
1552 function should specify a list of CAs for the server to send to the
1553 client and return that same list. The list will be used to verify
1554 that C{get_client_ca_list} returns the proper value at various
1555 times.
1556 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001557 server = self._server(None)
1558 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001559 self.assertEqual(client.get_client_ca_list(), [])
1560 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001561 ctx = server.get_context()
1562 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001563 self.assertEqual(client.get_client_ca_list(), [])
1564 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001565 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001566 self.assertEqual(client.get_client_ca_list(), expected)
1567 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001568
1569
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001570 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001571 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001572 L{Context.set_client_ca_list} raises a L{TypeError} if called with a
1573 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001574 """
1575 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001576 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
1577 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
1578 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001579
1580
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001581 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001582 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001583 If passed an empty list, L{Context.set_client_ca_list} configures the
1584 context to send no CA names to the client and, on both the server and
1585 client sides, L{Connection.get_client_ca_list} returns an empty list
1586 after the connection is set up.
1587 """
1588 def no_ca(ctx):
1589 ctx.set_client_ca_list([])
1590 return []
1591 self._check_client_ca_list(no_ca)
1592
1593
1594 def test_set_one_ca_list(self):
1595 """
1596 If passed a list containing a single X509Name,
1597 L{Context.set_client_ca_list} configures the context to send that CA
1598 name to the client and, on both the server and client sides,
1599 L{Connection.get_client_ca_list} returns a list containing that
1600 X509Name after the connection is set up.
1601 """
1602 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1603 cadesc = cacert.get_subject()
1604 def single_ca(ctx):
1605 ctx.set_client_ca_list([cadesc])
1606 return [cadesc]
1607 self._check_client_ca_list(single_ca)
1608
1609
1610 def test_set_multiple_ca_list(self):
1611 """
1612 If passed a list containing multiple X509Name objects,
1613 L{Context.set_client_ca_list} configures the context to send those CA
1614 names to the client and, on both the server and client sides,
1615 L{Connection.get_client_ca_list} returns a list containing those
1616 X509Names after the connection is set up.
1617 """
1618 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1619 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1620
1621 sedesc = secert.get_subject()
1622 cldesc = clcert.get_subject()
1623
1624 def multiple_ca(ctx):
1625 L = [sedesc, cldesc]
1626 ctx.set_client_ca_list(L)
1627 return L
1628 self._check_client_ca_list(multiple_ca)
1629
1630
1631 def test_reset_ca_list(self):
1632 """
1633 If called multiple times, only the X509Names passed to the final call
1634 of L{Context.set_client_ca_list} are used to configure the CA names
1635 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001636 """
1637 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1638 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1639 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1640
1641 cadesc = cacert.get_subject()
1642 sedesc = secert.get_subject()
1643 cldesc = clcert.get_subject()
1644
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001645 def changed_ca(ctx):
1646 ctx.set_client_ca_list([sedesc, cldesc])
1647 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001648 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001649 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001650
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001651
1652 def test_mutated_ca_list(self):
1653 """
1654 If the list passed to L{Context.set_client_ca_list} is mutated
1655 afterwards, this does not affect the list of CA names sent to the
1656 client.
1657 """
1658 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1659 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1660
1661 cadesc = cacert.get_subject()
1662 sedesc = secert.get_subject()
1663
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001664 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001665 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001666 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001667 L.append(sedesc)
1668 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001669 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001670
1671
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001672 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001673 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001674 L{Context.add_client_ca} raises L{TypeError} if called with a non-X509
1675 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001676 """
1677 ctx = Context(TLSv1_METHOD)
1678 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001679 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001680 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001681 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001682
1683
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001684 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001685 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001686 A certificate's subject can be added as a CA to be sent to the client
1687 with L{Context.add_client_ca}.
1688 """
1689 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1690 cadesc = cacert.get_subject()
1691 def single_ca(ctx):
1692 ctx.add_client_ca(cacert)
1693 return [cadesc]
1694 self._check_client_ca_list(single_ca)
1695
1696
1697 def test_multiple_add_client_ca(self):
1698 """
1699 Multiple CA names can be sent to the client by calling
1700 L{Context.add_client_ca} with multiple X509 objects.
1701 """
1702 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1703 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1704
1705 cadesc = cacert.get_subject()
1706 sedesc = secert.get_subject()
1707
1708 def multiple_ca(ctx):
1709 ctx.add_client_ca(cacert)
1710 ctx.add_client_ca(secert)
1711 return [cadesc, sedesc]
1712 self._check_client_ca_list(multiple_ca)
1713
1714
1715 def test_set_and_add_client_ca(self):
1716 """
1717 A call to L{Context.set_client_ca_list} followed by a call to
1718 L{Context.add_client_ca} results in using the CA names from the first
1719 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001720 """
1721 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1722 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1723 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1724
1725 cadesc = cacert.get_subject()
1726 sedesc = secert.get_subject()
1727 cldesc = clcert.get_subject()
1728
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001729 def mixed_set_add_ca(ctx):
1730 ctx.set_client_ca_list([cadesc, sedesc])
1731 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001732 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001733 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001734
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001735
1736 def test_set_after_add_client_ca(self):
1737 """
1738 A call to L{Context.set_client_ca_list} after a call to
1739 L{Context.add_client_ca} replaces the CA name specified by the former
1740 call with the names specified by the latter cal.
1741 """
1742 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1743 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1744 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1745
1746 cadesc = cacert.get_subject()
1747 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001748
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001749 def set_replaces_add_ca(ctx):
1750 ctx.add_client_ca(clcert)
1751 ctx.set_client_ca_list([cadesc])
1752 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001753 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001754 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001755
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001756
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04001757class InfoConstantTests(TestCase):
1758 """
1759 Tests for assorted constants exposed for use in info callbacks.
1760 """
1761 def test_integers(self):
1762 """
1763 All of the info constants are integers.
1764
1765 This is a very weak test. It would be nice to have one that actually
1766 verifies that as certain info events happen, the value passed to the
1767 info callback matches up with the constant exposed by OpenSSL.SSL.
1768 """
1769 for const in [
1770 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
1771 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
1772 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
1773 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
1774 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
1775 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
1776
1777 self.assertTrue(isinstance(const, int))
1778
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001779
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001780if __name__ == '__main__':
1781 main()