blob: 11674968dba9dad6d41cc366812a3dd86885fa5f [file] [log] [blame]
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04001# Copyright (C) Jean-Paul Calderone 2008, All rights reserved
2
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04003"""
4Unit tests for L{OpenSSL.SSL}.
5"""
6
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04007from twisted.internet.ssl import *
8
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04009from errno import ECONNREFUSED, EINPROGRESS
Jean-Paul Calderone52f0d8b2009-03-07 09:10:19 -050010from sys import platform
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -040011from socket import error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040012from os import makedirs
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -040013from os.path import join
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040014from unittest import main
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050015
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040016from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM, PKey, X509, X509Extension, dump_privatekey, load_certificate, dump_certificate, load_privatekey, X509_verify_cert_error_string
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -040017from OpenSSL.SSL import SysCallError, WantReadError, WantWriteError, ZeroReturnError, Context, ContextType, Connection, ConnectionType, Error
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040018from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040019from OpenSSL.SSL import SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD
Jean-Paul Calderone68649052009-07-17 21:14:27 -040020from OpenSSL.SSL import OP_NO_SSLv2, OP_NO_SSLv3, OP_SINGLE_DH_USE
Rick Deanb71c0d22009-04-01 14:09:23 -050021from OpenSSL.SSL import VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040022from OpenSSL.test.util import TestCase
Jean-Paul Calderone18808652009-07-05 12:54:05 -040023from OpenSSL.test.test_crypto import cleartextCertificatePEM, cleartextPrivateKeyPEM
Rick Dean94e46fd2009-07-18 14:51:24 -050024from OpenSSL.test.test_crypto import client_cert_pem, client_key_pem, server_cert_pem, server_key_pem, root_cert_pem
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050025try:
26 from OpenSSL.SSL import OP_NO_QUERY_MTU
27except ImportError:
28 OP_NO_QUERY_MTU = None
29try:
30 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
31except ImportError:
32 OP_COOKIE_EXCHANGE = None
33try:
34 from OpenSSL.SSL import OP_NO_TICKET
35except ImportError:
36 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040037
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040038
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040039def verify_cb(conn, cert, errnum, depth, ok):
40 print conn, cert, X509_verify_cert_error_string(errnum), depth, ok
41 return ok
42
Rick Deanb1ccd562009-07-09 23:52:39 -050043def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040044 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -040045 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040046 """
47 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -050048 port = socket()
49 port.bind(('', 0))
50 port.listen(1)
51 client = socket()
52 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -040053 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040054 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -050055 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -050056
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040057 # Let's pass some unencrypted data to make sure our socket connection is
58 # fine. Just one byte, so we don't have to worry about buffers getting
59 # filled up or fragmentation.
60 server.send("x")
61 assert client.recv(1024) == "x"
62 client.send("y")
63 assert server.recv(1024) == "y"
Rick Deanb1ccd562009-07-09 23:52:39 -050064
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -040065 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040066 server.setblocking(False)
67 client.setblocking(False)
68
Rick Deanb1ccd562009-07-09 23:52:39 -050069 return (server, client)
70
71
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040072
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040073class _LoopbackMixin:
74 def _loopback(self):
75 (server, client) = socket_pair()
76
77 ctx = Context(TLSv1_METHOD)
78 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
79 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
80 server = Connection(ctx, server)
81 server.set_accept_state()
82 client = Connection(Context(TLSv1_METHOD), client)
83 client.set_connect_state()
84
85 for i in range(3):
86 for conn in [client, server]:
87 try:
88 conn.do_handshake()
89 except WantReadError:
90 pass
91
92 server.setblocking(True)
93 client.setblocking(True)
94 return server, client
95
96
97 def _interactInMemory(self, client_conn, server_conn):
98 """
99 Try to read application bytes from each of the two L{Connection}
100 objects. Copy bytes back and forth between their send/receive buffers
101 for as long as there is anything to copy. When there is nothing more
102 to copy, return C{None}. If one of them actually manages to deliver
103 some application bytes, return a two-tuple of the connection from which
104 the bytes were read and the bytes themselves.
105 """
106 wrote = True
107 while wrote:
108 # Loop until neither side has anything to say
109 wrote = False
110
111 # Copy stuff from each side's send buffer to the other side's
112 # receive buffer.
113 for (read, write) in [(client_conn, server_conn),
114 (server_conn, client_conn)]:
115
116 # Give the side a chance to generate some more bytes, or
117 # succeed.
118 try:
119 bytes = read.recv(2 ** 16)
120 except WantReadError:
121 # It didn't succeed, so we'll hope it generated some
122 # output.
123 pass
124 else:
125 # It did succeed, so we'll stop now and let the caller deal
126 # with it.
127 return (read, bytes)
128
129 while True:
130 # Keep copying as long as there's more stuff there.
131 try:
132 dirty = read.bio_read(4096)
133 except WantReadError:
134 # Okay, nothing more waiting to be sent. Stop
135 # processing this send buffer.
136 break
137 else:
138 # Keep track of the fact that someone generated some
139 # output.
140 wrote = True
141 write.bio_write(dirty)
142
143
144
145class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400146 """
147 Unit tests for L{OpenSSL.SSL.Context}.
148 """
149 def test_method(self):
150 """
151 L{Context} can be instantiated with one of L{SSLv2_METHOD},
152 L{SSLv3_METHOD}, L{SSLv23_METHOD}, or L{TLSv1_METHOD}.
153 """
154 for meth in [SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]:
155 Context(meth)
156 self.assertRaises(TypeError, Context, "")
157 self.assertRaises(ValueError, Context, 10)
158
159
Rick Deane15b1472009-07-09 15:53:42 -0500160 def test_type(self):
161 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400162 L{Context} and L{ContextType} refer to the same type object and can be
163 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500164 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400165 self.assertIdentical(Context, ContextType)
166 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500167
168
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400169 def test_use_privatekey(self):
170 """
171 L{Context.use_privatekey} takes an L{OpenSSL.crypto.PKey} instance.
172 """
173 key = PKey()
174 key.generate_key(TYPE_RSA, 128)
175 ctx = Context(TLSv1_METHOD)
176 ctx.use_privatekey(key)
177 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400178
179
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400180 def test_set_app_data_wrong_args(self):
181 """
182 L{Context.set_app_data} raises L{TypeError} if called with other than
183 one argument.
184 """
185 context = Context(TLSv1_METHOD)
186 self.assertRaises(TypeError, context.set_app_data)
187 self.assertRaises(TypeError, context.set_app_data, None, None)
188
189
190 def test_get_app_data_wrong_args(self):
191 """
192 L{Context.get_app_data} raises L{TypeError} if called with any
193 arguments.
194 """
195 context = Context(TLSv1_METHOD)
196 self.assertRaises(TypeError, context.get_app_data, None)
197
198
199 def test_app_data(self):
200 """
201 L{Context.set_app_data} stores an object for later retrieval using
202 L{Context.get_app_data}.
203 """
204 app_data = object()
205 context = Context(TLSv1_METHOD)
206 context.set_app_data(app_data)
207 self.assertIdentical(context.get_app_data(), app_data)
208
209
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400210 def test_set_options_wrong_args(self):
211 """
212 L{Context.set_options} raises L{TypeError} if called with the wrong
213 number of arguments or a non-C{int} argument.
214 """
215 context = Context(TLSv1_METHOD)
216 self.assertRaises(TypeError, context.set_options)
217 self.assertRaises(TypeError, context.set_options, None)
218 self.assertRaises(TypeError, context.set_options, 1, None)
219
220
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400221 def test_set_timeout_wrong_args(self):
222 """
223 L{Context.set_timeout} raises L{TypeError} if called with the wrong
224 number of arguments or a non-C{int} argument.
225 """
226 context = Context(TLSv1_METHOD)
227 self.assertRaises(TypeError, context.set_timeout)
228 self.assertRaises(TypeError, context.set_timeout, None)
229 self.assertRaises(TypeError, context.set_timeout, 1, None)
230
231
232 def test_get_timeout_wrong_args(self):
233 """
234 L{Context.get_timeout} raises L{TypeError} if called with any arguments.
235 """
236 context = Context(TLSv1_METHOD)
237 self.assertRaises(TypeError, context.get_timeout, None)
238
239
240 def test_timeout(self):
241 """
242 L{Context.set_timeout} sets the session timeout for all connections
243 created using the context object. L{Context.get_timeout} retrieves this
244 value.
245 """
246 context = Context(TLSv1_METHOD)
247 context.set_timeout(1234)
248 self.assertEquals(context.get_timeout(), 1234)
249
250
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400251 def test_set_verify_depth_wrong_args(self):
252 """
253 L{Context.set_verify_depth} raises L{TypeError} if called with the wrong
254 number of arguments or a non-C{int} argument.
255 """
256 context = Context(TLSv1_METHOD)
257 self.assertRaises(TypeError, context.set_verify_depth)
258 self.assertRaises(TypeError, context.set_verify_depth, None)
259 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
260
261
262 def test_get_verify_depth_wrong_args(self):
263 """
264 L{Context.get_verify_depth} raises L{TypeError} if called with any arguments.
265 """
266 context = Context(TLSv1_METHOD)
267 self.assertRaises(TypeError, context.get_verify_depth, None)
268
269
270 def test_verify_depth(self):
271 """
272 L{Context.set_verify_depth} sets the number of certificates in a chain
273 to follow before giving up. The value can be retrieved with
274 L{Context.get_verify_depth}.
275 """
276 context = Context(TLSv1_METHOD)
277 context.set_verify_depth(11)
278 self.assertEquals(context.get_verify_depth(), 11)
279
280
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400281 def _write_encrypted_pem(self, passphrase):
282 key = PKey()
283 key.generate_key(TYPE_RSA, 128)
284 pemFile = self.mktemp()
285 fObj = file(pemFile, 'w')
286 fObj.write(dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase))
287 fObj.close()
288 return pemFile
289
290
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400291 def test_set_passwd_cb_wrong_args(self):
292 """
293 L{Context.set_passwd_cb} raises L{TypeError} if called with the
294 wrong arguments or with a non-callable first argument.
295 """
296 context = Context(TLSv1_METHOD)
297 self.assertRaises(TypeError, context.set_passwd_cb)
298 self.assertRaises(TypeError, context.set_passwd_cb, None)
299 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
300
301
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400302 def test_set_passwd_cb(self):
303 """
304 L{Context.set_passwd_cb} accepts a callable which will be invoked when
305 a private key is loaded from an encrypted PEM.
306 """
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400307 passphrase = "foobar"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400308 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400309 calledWith = []
310 def passphraseCallback(maxlen, verify, extra):
311 calledWith.append((maxlen, verify, extra))
312 return passphrase
313 context = Context(TLSv1_METHOD)
314 context.set_passwd_cb(passphraseCallback)
315 context.use_privatekey_file(pemFile)
316 self.assertTrue(len(calledWith), 1)
317 self.assertTrue(isinstance(calledWith[0][0], int))
318 self.assertTrue(isinstance(calledWith[0][1], int))
319 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400320
321
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400322 def test_passwd_callback_exception(self):
323 """
324 L{Context.use_privatekey_file} propagates any exception raised by the
325 passphrase callback.
326 """
327 pemFile = self._write_encrypted_pem("monkeys are nice")
328 def passphraseCallback(maxlen, verify, extra):
329 raise RuntimeError("Sorry, I am a fail.")
330
331 context = Context(TLSv1_METHOD)
332 context.set_passwd_cb(passphraseCallback)
333 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
334
335
336 def test_passwd_callback_false(self):
337 """
338 L{Context.use_privatekey_file} raises L{OpenSSL.SSL.Error} if the
339 passphrase callback returns a false value.
340 """
341 pemFile = self._write_encrypted_pem("monkeys are nice")
342 def passphraseCallback(maxlen, verify, extra):
343 return None
344
345 context = Context(TLSv1_METHOD)
346 context.set_passwd_cb(passphraseCallback)
347 self.assertRaises(Error, context.use_privatekey_file, pemFile)
348
349
350 def test_passwd_callback_non_string(self):
351 """
352 L{Context.use_privatekey_file} raises L{OpenSSL.SSL.Error} if the
353 passphrase callback returns a true non-string value.
354 """
355 pemFile = self._write_encrypted_pem("monkeys are nice")
356 def passphraseCallback(maxlen, verify, extra):
357 return 10
358
359 context = Context(TLSv1_METHOD)
360 context.set_passwd_cb(passphraseCallback)
361 self.assertRaises(Error, context.use_privatekey_file, pemFile)
362
363
364 def test_passwd_callback_too_long(self):
365 """
366 If the passphrase returned by the passphrase callback returns a string
367 longer than the indicated maximum length, it is truncated.
368 """
369 # A priori knowledge!
370 passphrase = "x" * 1024
371 pemFile = self._write_encrypted_pem(passphrase)
372 def passphraseCallback(maxlen, verify, extra):
373 assert maxlen == 1024
374 return passphrase + "y"
375
376 context = Context(TLSv1_METHOD)
377 context.set_passwd_cb(passphraseCallback)
378 # This shall succeed because the truncated result is the correct
379 # passphrase.
380 context.use_privatekey_file(pemFile)
381
382
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400383 def test_set_info_callback(self):
384 """
385 L{Context.set_info_callback} accepts a callable which will be invoked
386 when certain information about an SSL connection is available.
387 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500388 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400389
390 clientSSL = Connection(Context(TLSv1_METHOD), client)
391 clientSSL.set_connect_state()
392
393 called = []
394 def info(conn, where, ret):
395 called.append((conn, where, ret))
396 context = Context(TLSv1_METHOD)
397 context.set_info_callback(info)
398 context.use_certificate(
399 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
400 context.use_privatekey(
401 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
402
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400403 serverSSL = Connection(context, server)
404 serverSSL.set_accept_state()
405
406 while not called:
407 for ssl in clientSSL, serverSSL:
408 try:
409 ssl.do_handshake()
410 except WantReadError:
411 pass
412
413 # Kind of lame. Just make sure it got called somehow.
414 self.assertTrue(called)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400415
416
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400417 def _load_verify_locations_test(self, *args):
Rick Deanb1ccd562009-07-09 23:52:39 -0500418 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400419
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400420 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400421 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400422 # Require that the server certificate verify properly or the
423 # connection will fail.
424 clientContext.set_verify(
425 VERIFY_PEER,
426 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
427
428 clientSSL = Connection(clientContext, client)
429 clientSSL.set_connect_state()
430
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400431 serverContext = Context(TLSv1_METHOD)
432 serverContext.use_certificate(
433 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
434 serverContext.use_privatekey(
435 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
436
437 serverSSL = Connection(serverContext, server)
438 serverSSL.set_accept_state()
439
440 for i in range(3):
441 for ssl in clientSSL, serverSSL:
442 try:
443 # Without load_verify_locations above, the handshake
444 # will fail:
445 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
446 # 'certificate verify failed')]
447 ssl.do_handshake()
448 except WantReadError:
449 pass
450
451 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400452 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400453
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500454
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400455 def test_load_verify_file(self):
456 """
457 L{Context.load_verify_locations} accepts a file name and uses the
458 certificates within for verification purposes.
459 """
460 cafile = self.mktemp()
461 fObj = file(cafile, 'w')
462 fObj.write(cleartextCertificatePEM)
463 fObj.close()
464
465 self._load_verify_locations_test(cafile)
466
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400467
468 def test_load_verify_invalid_file(self):
469 """
470 L{Context.load_verify_locations} raises L{Error} when passed a
471 non-existent cafile.
472 """
473 clientContext = Context(TLSv1_METHOD)
474 self.assertRaises(
475 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400476
477
478 def test_load_verify_directory(self):
479 """
480 L{Context.load_verify_locations} accepts a directory name and uses
481 the certificates within for verification purposes.
482 """
483 capath = self.mktemp()
484 makedirs(capath)
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -0400485 # Hash value computed manually with c_rehash to avoid depending on
486 # c_rehash in the test suite.
487 cafile = join(capath, 'c7adac82.0')
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400488 fObj = file(cafile, 'w')
489 fObj.write(cleartextCertificatePEM)
490 fObj.close()
491
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400492 self._load_verify_locations_test(None, capath)
493
494
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400495 def test_load_verify_locations_wrong_args(self):
496 """
497 L{Context.load_verify_locations} raises L{TypeError} if called with
498 the wrong number of arguments or with non-C{str} arguments.
499 """
500 context = Context(TLSv1_METHOD)
501 self.assertRaises(TypeError, context.load_verify_locations)
502 self.assertRaises(TypeError, context.load_verify_locations, object())
503 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
504 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
505
506
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400507 if platform == "win32":
508 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400509 "See LP#404343 and LP#404344."
510 else:
511 def test_set_default_verify_paths(self):
512 """
513 L{Context.set_default_verify_paths} causes the platform-specific CA
514 certificate locations to be used for verification purposes.
515 """
516 # Testing this requires a server with a certificate signed by one of
517 # the CAs in the platform CA location. Getting one of those costs
518 # money. Fortunately (or unfortunately, depending on your
519 # perspective), it's easy to think of a public server on the
520 # internet which has such a certificate. Connecting to the network
521 # in a unit test is bad, but it's the only way I can think of to
522 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400523
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400524 # Arg, verisign.com doesn't speak TLSv1
525 context = Context(SSLv3_METHOD)
526 context.set_default_verify_paths()
527 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200528 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400529 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400530
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400531 client = socket()
532 client.connect(('verisign.com', 443))
533 clientSSL = Connection(context, client)
534 clientSSL.set_connect_state()
535 clientSSL.do_handshake()
536 clientSSL.send('GET / HTTP/1.0\r\n\r\n')
537 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400538
539
540 def test_set_default_verify_paths_signature(self):
541 """
542 L{Context.set_default_verify_paths} takes no arguments and raises
543 L{TypeError} if given any.
544 """
545 context = Context(TLSv1_METHOD)
546 self.assertRaises(TypeError, context.set_default_verify_paths, None)
547 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
548 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500549
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400550
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500551 def test_add_extra_chain_cert_invalid_cert(self):
552 """
553 L{Context.add_extra_chain_cert} raises L{TypeError} if called with
554 other than one argument or if called with an object which is not an
555 instance of L{X509}.
556 """
557 context = Context(TLSv1_METHOD)
558 self.assertRaises(TypeError, context.add_extra_chain_cert)
559 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
560 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
561
562
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400563 def _create_certificate_chain(self):
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500564 """
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400565 Construct and return a chain of certificates.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400566
567 1. A new self-signed certificate authority certificate (cacert)
568 2. A new intermediate certificate signed by cacert (icert)
569 3. A new server certificate signed by icert (scert)
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500570 """
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400571 caext = X509Extension('basicConstraints', True, 'CA:true')
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500572
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400573 # Step 1
574 cakey = PKey()
575 cakey.generate_key(TYPE_RSA, 512)
576 cacert = X509()
577 cacert.get_subject().commonName = "CA Certificate"
578 cacert.set_issuer(cacert.get_subject())
579 cacert.set_pubkey(cakey)
580 cacert.gmtime_adj_notBefore(0)
581 cacert.gmtime_adj_notAfter(6000)
582 cacert.add_extensions([caext])
583 cacert.sign(cakey, "sha")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500584
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400585 # Step 2
586 ikey = PKey()
587 ikey.generate_key(TYPE_RSA, 512)
588 icert = X509()
589 icert.get_subject().commonName = "Intermediate Certificate"
590 icert.set_issuer(cacert.get_subject())
591 icert.set_pubkey(ikey)
592 icert.gmtime_adj_notBefore(0)
593 icert.gmtime_adj_notAfter(6000)
594 icert.add_extensions([caext])
595 icert.sign(cakey, "sha")
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400596
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400597 # Step 3
598 skey = PKey()
599 skey.generate_key(TYPE_RSA, 512)
600 scert = X509()
601 scert.get_subject().commonName = "Server Certificate"
602 scert.set_issuer(icert.get_subject())
603 scert.set_pubkey(skey)
604 scert.gmtime_adj_notBefore(0)
605 scert.gmtime_adj_notAfter(6000)
606 scert.sign(ikey, "sha")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400607
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400608 # # Step 1
609 # cakey = KeyPair.generate()
610 # cacert = cakey.selfSignedCert(1, commonName="CA Certificate")
611
612 # # Step 2
613 # ikey = KeyPair.generate()
614 # ireq = ikey.certificateRequest(DN(commonName="Intermediate Certificate"))
615 # icert = PrivateCertificate.load(
616 # cacert.signCertificateRequest(ireq, lambda dn: True, 1),
617 # ikey)
618
619 # # Step 3
620 # skey = KeyPair.generate()
621 # sreq = skey.certificateRequest(DN(commonName="Server Certificate"))
622 # scert = PrivateCertificate.load(
623 # icert.signCertificateRequest(sreq, lambda dn: True, 2),
624 # skey)
625
626 # cakey = cakey.original
627 # cacert = cacert.original
628 # ikey = ikey.original
629 # icert = icert.original
630 # skey = skey.original
631 # scert = scert.original
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400632 return [(cakey, cacert), (ikey, icert), (skey, scert)]
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400633
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400634
635 def _handshake_test(self, serverContext, clientContext):
636 """
637 Verify that a client and server created with the given contexts can
638 successfully handshake and communicate.
639 """
640 serverSocket, clientSocket = socket_pair()
641
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400642 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400643 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400644
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400645 client = Connection(clientContext, clientSocket)
646 client.set_connect_state()
647
648 # Make them talk to each other.
649 # self._interactInMemory(client, server)
650 for i in range(3):
651 for s in [client, server]:
652 try:
653 s.do_handshake()
654 except WantReadError:
655 pass
656
657
658 def test_add_extra_chain_cert(self):
659 """
660 L{Context.add_extra_chain_cert} accepts an L{X509} instance to add to
661 the certificate chain.
662
663 See L{_create_certificate_chain} for the details of the certificate
664 chain tested.
665
666 The chain is tested by starting a server with scert and connecting
667 to it with a client which trusts cacert and requires verification to
668 succeed.
669 """
670 chain = self._create_certificate_chain()
671 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
672
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400673 # Dump the CA certificate to a file because that's the only way to load
674 # it as a trusted CA in the client context.
675 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
676 fObj = file(name, 'w')
677 fObj.write(dump_certificate(FILETYPE_PEM, cert))
678 fObj.close()
679
680 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
681 fObj = file(name, 'w')
682 fObj.write(dump_privatekey(FILETYPE_PEM, key))
683 fObj.close()
684
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400685 # Create the server context
686 serverContext = Context(TLSv1_METHOD)
687 serverContext.use_privatekey(skey)
688 serverContext.use_certificate(scert)
689 serverContext.add_extra_chain_cert(cacert)
690 serverContext.add_extra_chain_cert(icert)
691
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400692 # Create the client
693 clientContext = Context(TLSv1_METHOD)
694 clientContext.set_verify(
695 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
696 clientContext.load_verify_locations('ca.pem')
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400697
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400698 # Try it out.
699 self._handshake_test(serverContext, clientContext)
700
701
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400702 def test_use_certificate_chain_file(self):
703 """
704 L{Context.use_certificate_chain_file} reads a certificate chain from
705 the specified file.
706
707 The chain is tested by starting a server with scert and connecting
708 to it with a client which trusts cacert and requires verification to
709 succeed.
710 """
711 chain = self._create_certificate_chain()
712 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
713
714 # Write out the chain file.
715 chainFile = self.mktemp()
716 fObj = file(chainFile, 'w')
717 # Most specific to least general.
718 fObj.write(dump_certificate(FILETYPE_PEM, scert))
719 fObj.write(dump_certificate(FILETYPE_PEM, icert))
720 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
721 fObj.close()
722
723 serverContext = Context(TLSv1_METHOD)
724 serverContext.use_certificate_chain_file(chainFile)
725 serverContext.use_privatekey(skey)
726
727 fObj = file('ca.pem', 'w')
728 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
729 fObj.close()
730
731 clientContext = Context(TLSv1_METHOD)
732 clientContext.set_verify(
733 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
734 clientContext.load_verify_locations('ca.pem')
735
736 self._handshake_test(serverContext, clientContext)
737
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -0400738 # XXX load_client_ca
739 # XXX set_session_id
740 # XXX get_verify
741 # XXX load_temp_dh
742 # XXX set_cipher_list
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400743
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400744
745
746class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -0500747 """
748 Unit tests for L{OpenSSL.SSL.Connection}.
749 """
750 def test_type(self):
751 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400752 L{Connection} and L{ConnectionType} refer to the same type object and
753 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500754 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400755 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -0500756 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400757 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -0500758
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400759
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -0500760 def test_get_context(self):
761 """
762 L{Connection.get_context} returns the L{Context} instance used to
763 construct the L{Connection} instance.
764 """
765 context = Context(TLSv1_METHOD)
766 connection = Connection(context, None)
767 self.assertIdentical(connection.get_context(), context)
768
769
770 def test_get_context_wrong_args(self):
771 """
772 L{Connection.get_context} raises L{TypeError} if called with any
773 arguments.
774 """
775 connection = Connection(Context(TLSv1_METHOD), None)
776 self.assertRaises(TypeError, connection.get_context, None)
777
778
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -0400779 def test_pending(self):
780 connection = Connection(Context(TLSv1_METHOD), None)
781 self.assertEquals(connection.pending(), 0)
782
783
784 def test_pending_wrong_args(self):
785 connection = Connection(Context(TLSv1_METHOD), None)
786 self.assertRaises(TypeError, connection.pending, None)
787
788
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400789 def test_connect_wrong_args(self):
790 connection = Connection(Context(TLSv1_METHOD), socket())
791 self.assertRaises(TypeError, connection.connect, None)
792
793
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400794 def test_connect_refused(self):
795 client = socket()
796 context = Context(TLSv1_METHOD)
797 clientSSL = Connection(context, client)
798 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -0400799 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400800
801
802 def test_connect(self):
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400803 port = socket()
804 port.bind(('', 0))
805 port.listen(3)
806
807 clientSSL = Connection(Context(TLSv1_METHOD), socket())
808 clientSSL.connect(port.getsockname())
809
810
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -0400811 def test_connect_ex(self):
812 port = socket()
813 port.bind(('', 0))
814 port.listen(3)
815
816 clientSSL = Connection(Context(TLSv1_METHOD), socket())
817 clientSSL.setblocking(False)
818 self.assertEquals(
819 clientSSL.connect_ex(port.getsockname()), EINPROGRESS)
820
821
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400822 def test_accept_wrong_args(self):
823 connection = Connection(Context(TLSv1_METHOD), socket())
824 self.assertRaises(TypeError, connection.accept, None)
825
826
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400827 def test_accept(self):
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400828 ctx = Context(TLSv1_METHOD)
829 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
830 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400831 port = socket()
832 portSSL = Connection(ctx, port)
833 portSSL.bind(('', 0))
834 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400835
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400836 clientSSL = Connection(Context(TLSv1_METHOD), socket())
837 clientSSL.connect(portSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400838
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400839 serverSSL, address = portSSL.accept()
840
841 self.assertTrue(isinstance(serverSSL, Connection))
842 self.assertIdentical(serverSSL.get_context(), ctx)
843 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400844
845
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400846 def test_shutdown_wrong_args(self):
847 connection = Connection(Context(TLSv1_METHOD), None)
848 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -0400849 self.assertRaises(TypeError, connection.get_shutdown, None)
850 self.assertRaises(TypeError, connection.set_shutdown)
851 self.assertRaises(TypeError, connection.set_shutdown, None)
852 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400853
854
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400855 def test_shutdown(self):
856 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -0400857 self.assertFalse(server.shutdown())
858 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400859 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -0400860 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
861 client.shutdown()
862 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
863 self.assertRaises(ZeroReturnError, server.recv, 1024)
864 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400865
866
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -0400867 def test_set_shutdown(self):
868 connection = Connection(Context(TLSv1_METHOD), socket())
869 connection.set_shutdown(RECEIVED_SHUTDOWN)
870 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
871
872
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400873 def test_app_data_wrong_args(self):
874 conn = Connection(Context(TLSv1_METHOD), None)
875 self.assertRaises(TypeError, conn.get_app_data, None)
876 self.assertRaises(TypeError, conn.set_app_data)
877 self.assertRaises(TypeError, conn.set_app_data, None, None)
878
879
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -0400880 def test_app_data(self):
881 conn = Connection(Context(TLSv1_METHOD), None)
882 app_data = object()
883 conn.set_app_data(app_data)
884 self.assertIdentical(conn.get_app_data(), app_data)
885
886
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400887 def test_makefile(self):
888 conn = Connection(Context(TLSv1_METHOD), None)
889 self.assertRaises(NotImplementedError, conn.makefile)
890
891
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400892
Jean-Paul Calderonef135e622010-07-28 19:14:16 -0400893class ConnectionGetCipherListTests(TestCase):
894 def test_wrongargs(self):
895 connection = Connection(Context(TLSv1_METHOD), None)
896 self.assertRaises(TypeError, connection.get_cipher_list, None)
897
898
899 def test_result(self):
900 connection = Connection(Context(TLSv1_METHOD), None)
901 ciphers = connection.get_cipher_list()
902 self.assertTrue(isinstance(ciphers, list))
903 for cipher in ciphers:
904 self.assertTrue(isinstance(cipher, str))
905
906
907
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -0400908class ConnectionSendallTests(TestCase, _LoopbackMixin):
909 """
910 Tests for L{Connection.sendall}.
911 """
912 def test_wrongargs(self):
913 """
914 When called with arguments other than a single string,
915 L{Connection.sendall} raises L{TypeError}.
916 """
917 connection = Connection(Context(TLSv1_METHOD), None)
918 self.assertRaises(TypeError, connection.sendall)
919 self.assertRaises(TypeError, connection.sendall, object())
920 self.assertRaises(TypeError, connection.sendall, "foo", "bar")
921
922
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400923 def test_short(self):
924 """
925 L{Connection.sendall} transmits all of the bytes in the string passed to
926 it.
927 """
928 server, client = self._loopback()
929 server.sendall('x')
930 self.assertEquals(client.recv(1), 'x')
931
932
933 def test_long(self):
934 server, client = self._loopback()
935 message ='x' * 1024 * 128 + 'y'
936 server.sendall(message)
937 accum = []
938 received = 0
939 while received < len(message):
940 bytes = client.recv(1024)
941 accum.append(bytes)
942 received += len(bytes)
943 self.assertEquals(message, ''.join(accum))
944
945
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -0400946 def test_closed(self):
947 """
948 If the underlying socket is closed, L{Connection.sendall} propagates the
949 write error from the low level write call.
950 """
951 server, client = self._loopback()
952 client.close()
953 server.sendall("hello, world")
954 self.assertRaises(SysCallError, server.sendall, "hello, world")
955
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400956
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -0400957
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -0400958class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
959 """
960 Tests for SSL renegotiation APIs.
961 """
962 def test_renegotiate_wrong_args(self):
963 connection = Connection(Context(TLSv1_METHOD), None)
964 self.assertRaises(TypeError, connection.renegotiate, None)
965
966
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400967 def test_total_renegotiations_wrong_args(self):
968 connection = Connection(Context(TLSv1_METHOD), None)
969 self.assertRaises(TypeError, connection.total_renegotiations, None)
970
971
972 def test_total_renegotiations(self):
973 connection = Connection(Context(TLSv1_METHOD), None)
974 self.assertEquals(connection.total_renegotiations(), 0)
975
976
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -0400977# def test_renegotiate(self):
978# """
979# """
980# server, client = self._loopback()
981
982# server.send("hello world")
983# self.assertEquals(client.recv(len("hello world")), "hello world")
984
985# self.assertEquals(server.total_renegotiations(), 0)
986# self.assertTrue(server.renegotiate())
987
988# server.setblocking(False)
989# client.setblocking(False)
990# while server.renegotiate_pending():
991# client.do_handshake()
992# server.do_handshake()
993
994# self.assertEquals(server.total_renegotiations(), 1)
995
996
997
998
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400999class ErrorTests(TestCase):
1000 """
1001 Unit tests for L{OpenSSL.SSL.Error}.
1002 """
1003 def test_type(self):
1004 """
1005 L{Error} is an exception type.
1006 """
1007 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05001008 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05001009
1010
1011
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001012class ConstantsTests(TestCase):
1013 """
1014 Tests for the values of constants exposed in L{OpenSSL.SSL}.
1015
1016 These are values defined by OpenSSL intended only to be used as flags to
1017 OpenSSL APIs. The only assertions it seems can be made about them is
1018 their values.
1019 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001020 # unittest.TestCase has no skip mechanism
1021 if OP_NO_QUERY_MTU is not None:
1022 def test_op_no_query_mtu(self):
1023 """
1024 The value of L{OpenSSL.SSL.OP_NO_QUERY_MTU} is 0x1000, the value of
1025 I{SSL_OP_NO_QUERY_MTU} defined by I{openssl/ssl.h}.
1026 """
1027 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
1028 else:
1029 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001030
1031
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001032 if OP_COOKIE_EXCHANGE is not None:
1033 def test_op_cookie_exchange(self):
1034 """
1035 The value of L{OpenSSL.SSL.OP_COOKIE_EXCHANGE} is 0x2000, the value
1036 of I{SSL_OP_COOKIE_EXCHANGE} defined by I{openssl/ssl.h}.
1037 """
1038 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
1039 else:
1040 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001041
1042
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001043 if OP_NO_TICKET is not None:
1044 def test_op_no_ticket(self):
1045 """
1046 The value of L{OpenSSL.SSL.OP_NO_TICKET} is 0x4000, the value of
1047 I{SSL_OP_NO_TICKET} defined by I{openssl/ssl.h}.
1048 """
1049 self.assertEqual(OP_NO_TICKET, 0x4000)
1050 else:
1051 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05001052
1053
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04001054
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001055class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05001056 """
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001057 Tests for L{OpenSSL.SSL.Connection} using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05001058 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001059 def _server(self, sock):
1060 """
1061 Create a new server-side SSL L{Connection} object wrapped around
1062 C{sock}.
1063 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001064 # Create the server side Connection. This is mostly setup boilerplate
1065 # - use TLSv1, use a particular certificate, etc.
1066 server_ctx = Context(TLSv1_METHOD)
1067 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1068 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1069 server_store = server_ctx.get_cert_store()
1070 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1071 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1072 server_ctx.check_privatekey()
1073 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001074 # Here the Connection is actually created. If None is passed as the 2nd
1075 # parameter, it indicates a memory BIO should be created.
1076 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001077 server_conn.set_accept_state()
1078 return server_conn
1079
1080
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001081 def _client(self, sock):
1082 """
1083 Create a new client-side SSL L{Connection} object wrapped around
1084 C{sock}.
1085 """
1086 # Now create the client side Connection. Similar boilerplate to the
1087 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001088 client_ctx = Context(TLSv1_METHOD)
1089 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1090 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1091 client_store = client_ctx.get_cert_store()
1092 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
1093 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
1094 client_ctx.check_privatekey()
1095 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001096 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001097 client_conn.set_connect_state()
1098 return client_conn
1099
1100
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001101 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001102 """
1103 Two L{Connection}s which use memory BIOs can be manually connected by
1104 reading from the output of each and writing those bytes to the input of
1105 the other and in this way establish a connection and exchange
1106 application-level bytes with each other.
1107 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001108 server_conn = self._server(None)
1109 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001110
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001111 # There should be no key or nonces yet.
1112 self.assertIdentical(server_conn.master_key(), None)
1113 self.assertIdentical(server_conn.client_random(), None)
1114 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001115
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001116 # First, the handshake needs to happen. We'll deliver bytes back and
1117 # forth between the client and server until neither of them feels like
1118 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001119 self.assertIdentical(
1120 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001121
1122 # Now that the handshake is done, there should be a key and nonces.
1123 self.assertNotIdentical(server_conn.master_key(), None)
1124 self.assertNotIdentical(server_conn.client_random(), None)
1125 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04001126 self.assertEquals(server_conn.client_random(), client_conn.client_random())
1127 self.assertEquals(server_conn.server_random(), client_conn.server_random())
1128 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
1129 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001130
1131 # Here are the bytes we'll try to send.
Rick Deanb71c0d22009-04-01 14:09:23 -05001132 important_message = 'One if by land, two if by sea.'
1133
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001134 server_conn.write(important_message)
1135 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001136 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001137 (client_conn, important_message))
1138
1139 client_conn.write(important_message[::-1])
1140 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001141 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001142 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05001143
1144
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001145 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05001146 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001147 Just like L{test_memoryConnect} but with an actual socket.
1148
1149 This is primarily to rule out the memory BIO code as the source of
1150 any problems encountered while passing data over a L{Connection} (if
1151 this test fails, there must be a problem outside the memory BIO
1152 code, as no memory BIO is involved here). Even though this isn't a
1153 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05001154 """
1155 (server, client) = socket_pair()
1156
1157 # Let the encryption begin...
1158 client_conn = self._client(client)
Rick Deanb1ccd562009-07-09 23:52:39 -05001159 server_conn = self._server(server)
Jean-Paul Calderone7903cbd2009-07-16 12:23:34 -04001160
Rick Deanb1ccd562009-07-09 23:52:39 -05001161 # Establish the connection
1162 established = False
1163 while not established:
1164 established = True # assume the best
1165 for ssl in client_conn, server_conn:
1166 try:
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001167 # Generally a recv() or send() could also work instead
1168 # of do_handshake(), and we would stop on the first
Rick Deanb1ccd562009-07-09 23:52:39 -05001169 # non-exception.
1170 ssl.do_handshake()
1171 except WantReadError:
1172 established = False
1173
1174 important_message = "Help me Obi Wan Kenobi, you're my only hope."
1175 client_conn.send(important_message)
1176 msg = server_conn.recv(1024)
1177 self.assertEqual(msg, important_message)
1178
1179 # Again in the other direction, just for fun.
1180 important_message = important_message[::-1]
1181 server_conn.send(important_message)
1182 msg = client_conn.recv(1024)
1183 self.assertEqual(msg, important_message)
1184
1185
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04001186 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05001187 """
1188 Test that L{OpenSSL.SSL.bio_read} and L{OpenSSL.SSL.bio_write} don't
1189 work on L{OpenSSL.SSL.Connection}() that use sockets.
1190 """
1191 context = Context(SSLv3_METHOD)
1192 client = socket()
1193 clientSSL = Connection(context, client)
1194 self.assertRaises( TypeError, clientSSL.bio_read, 100)
1195 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04001196 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001197
1198
1199 def test_outgoingOverflow(self):
1200 """
1201 If more bytes than can be written to the memory BIO are passed to
1202 L{Connection.send} at once, the number of bytes which were written is
1203 returned and that many bytes from the beginning of the input can be
1204 read from the other end of the connection.
1205 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001206 server = self._server(None)
1207 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001208
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001209 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001210
1211 size = 2 ** 15
1212 sent = client.send("x" * size)
1213 # Sanity check. We're trying to test what happens when the entire
1214 # input can't be sent. If the entire input was sent, this test is
1215 # meaningless.
1216 self.assertTrue(sent < size)
1217
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001218 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001219 self.assertIdentical(receiver, server)
1220
1221 # We can rely on all of these bytes being received at once because
1222 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
1223 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001224
1225
1226 def test_shutdown(self):
1227 """
1228 L{Connection.bio_shutdown} signals the end of the data stream from
1229 which the L{Connection} reads.
1230 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001231 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001232 server.bio_shutdown()
1233 e = self.assertRaises(Error, server.recv, 1024)
1234 # We don't want WantReadError or ZeroReturnError or anything - it's a
1235 # handshake failure.
1236 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001237
1238
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001239 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001240 """
1241 Verify the return value of the C{get_client_ca_list} method for server and client connections.
1242
1243 @param func: A function which will be called with the server context
1244 before the client and server are connected to each other. This
1245 function should specify a list of CAs for the server to send to the
1246 client and return that same list. The list will be used to verify
1247 that C{get_client_ca_list} returns the proper value at various
1248 times.
1249 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001250 server = self._server(None)
1251 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001252 self.assertEqual(client.get_client_ca_list(), [])
1253 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001254 ctx = server.get_context()
1255 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001256 self.assertEqual(client.get_client_ca_list(), [])
1257 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001258 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001259 self.assertEqual(client.get_client_ca_list(), expected)
1260 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001261
1262
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001263 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001264 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001265 L{Context.set_client_ca_list} raises a L{TypeError} if called with a
1266 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001267 """
1268 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001269 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
1270 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
1271 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001272
1273
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001274 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001275 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001276 If passed an empty list, L{Context.set_client_ca_list} configures the
1277 context to send no CA names to the client and, on both the server and
1278 client sides, L{Connection.get_client_ca_list} returns an empty list
1279 after the connection is set up.
1280 """
1281 def no_ca(ctx):
1282 ctx.set_client_ca_list([])
1283 return []
1284 self._check_client_ca_list(no_ca)
1285
1286
1287 def test_set_one_ca_list(self):
1288 """
1289 If passed a list containing a single X509Name,
1290 L{Context.set_client_ca_list} configures the context to send that CA
1291 name to the client and, on both the server and client sides,
1292 L{Connection.get_client_ca_list} returns a list containing that
1293 X509Name after the connection is set up.
1294 """
1295 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1296 cadesc = cacert.get_subject()
1297 def single_ca(ctx):
1298 ctx.set_client_ca_list([cadesc])
1299 return [cadesc]
1300 self._check_client_ca_list(single_ca)
1301
1302
1303 def test_set_multiple_ca_list(self):
1304 """
1305 If passed a list containing multiple X509Name objects,
1306 L{Context.set_client_ca_list} configures the context to send those CA
1307 names to the client and, on both the server and client sides,
1308 L{Connection.get_client_ca_list} returns a list containing those
1309 X509Names after the connection is set up.
1310 """
1311 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1312 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1313
1314 sedesc = secert.get_subject()
1315 cldesc = clcert.get_subject()
1316
1317 def multiple_ca(ctx):
1318 L = [sedesc, cldesc]
1319 ctx.set_client_ca_list(L)
1320 return L
1321 self._check_client_ca_list(multiple_ca)
1322
1323
1324 def test_reset_ca_list(self):
1325 """
1326 If called multiple times, only the X509Names passed to the final call
1327 of L{Context.set_client_ca_list} are used to configure the CA names
1328 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001329 """
1330 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1331 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1332 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1333
1334 cadesc = cacert.get_subject()
1335 sedesc = secert.get_subject()
1336 cldesc = clcert.get_subject()
1337
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001338 def changed_ca(ctx):
1339 ctx.set_client_ca_list([sedesc, cldesc])
1340 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001341 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001342 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001343
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001344
1345 def test_mutated_ca_list(self):
1346 """
1347 If the list passed to L{Context.set_client_ca_list} is mutated
1348 afterwards, this does not affect the list of CA names sent to the
1349 client.
1350 """
1351 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1352 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1353
1354 cadesc = cacert.get_subject()
1355 sedesc = secert.get_subject()
1356
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001357 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001358 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001359 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001360 L.append(sedesc)
1361 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001362 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001363
1364
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001365 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001366 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001367 L{Context.add_client_ca} raises L{TypeError} if called with a non-X509
1368 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001369 """
1370 ctx = Context(TLSv1_METHOD)
1371 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001372 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001373 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001374 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001375
1376
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001377 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001378 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001379 A certificate's subject can be added as a CA to be sent to the client
1380 with L{Context.add_client_ca}.
1381 """
1382 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1383 cadesc = cacert.get_subject()
1384 def single_ca(ctx):
1385 ctx.add_client_ca(cacert)
1386 return [cadesc]
1387 self._check_client_ca_list(single_ca)
1388
1389
1390 def test_multiple_add_client_ca(self):
1391 """
1392 Multiple CA names can be sent to the client by calling
1393 L{Context.add_client_ca} with multiple X509 objects.
1394 """
1395 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1396 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1397
1398 cadesc = cacert.get_subject()
1399 sedesc = secert.get_subject()
1400
1401 def multiple_ca(ctx):
1402 ctx.add_client_ca(cacert)
1403 ctx.add_client_ca(secert)
1404 return [cadesc, sedesc]
1405 self._check_client_ca_list(multiple_ca)
1406
1407
1408 def test_set_and_add_client_ca(self):
1409 """
1410 A call to L{Context.set_client_ca_list} followed by a call to
1411 L{Context.add_client_ca} results in using the CA names from the first
1412 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001413 """
1414 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1415 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1416 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1417
1418 cadesc = cacert.get_subject()
1419 sedesc = secert.get_subject()
1420 cldesc = clcert.get_subject()
1421
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001422 def mixed_set_add_ca(ctx):
1423 ctx.set_client_ca_list([cadesc, sedesc])
1424 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001425 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001426 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001427
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001428
1429 def test_set_after_add_client_ca(self):
1430 """
1431 A call to L{Context.set_client_ca_list} after a call to
1432 L{Context.add_client_ca} replaces the CA name specified by the former
1433 call with the names specified by the latter cal.
1434 """
1435 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1436 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1437 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1438
1439 cadesc = cacert.get_subject()
1440 sedesc = secert.get_subject()
1441 cldesc = clcert.get_subject()
1442
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001443 def set_replaces_add_ca(ctx):
1444 ctx.add_client_ca(clcert)
1445 ctx.set_client_ca_list([cadesc])
1446 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001447 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001448 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001449
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001450
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001451
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001452if __name__ == '__main__':
1453 main()