diff options
Diffstat (limited to 'leakcheck')
-rw-r--r-- | leakcheck/context-info-callback.py | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/leakcheck/context-info-callback.py b/leakcheck/context-info-callback.py new file mode 100644 index 0000000..d4c9fa5 --- /dev/null +++ b/leakcheck/context-info-callback.py @@ -0,0 +1,96 @@ +# Copyright (C) Jean-Paul Calderone 2008, All rights reserved +# +# Stress tester for thread-related bugs in global_info_callback in +# src/ssl/context.c. In 0.7 and earlier, this will somewhat reliably +# segfault or abort after a few dozen to a few thousand iterations on an SMP +# machine (generally not on a UP machine) due to uses of Python/C API +# without holding the GIL. + +from itertools import count +from threading import Thread +from socket import socket + +from OpenSSL.SSL import Context, TLSv1_METHOD, Connection, WantReadError +from OpenSSL.crypto import FILETYPE_PEM, load_certificate, load_privatekey + +cleartextPrivateKeyPEM = ( + "-----BEGIN RSA PRIVATE KEY-----\n" + "MIICXAIBAAKBgQDaemNe1syksAbFFpF3aoOrZ18vB/IQNZrAjFqXPv9iieJm7+Tc\n" + "g+lA/v0qmoEKrpT2xfwxXmvZwBNM4ZhyRC3DPIFEyJV7/3IA1p5iuMY/GJI1VIgn\n" + "aikQCnrsyxtaRpsMBeZRniaVzcUJ+XnEdFGEjlo+k0xlwfVclDEMwgpXAQIDAQAB\n" + "AoGBALi0a7pMQqqgnriVAdpBVJveQtxSDVWi2/gZMKVZfzNheuSnv4amhtaKPKJ+\n" + "CMZtHkcazsE2IFvxRN/kgato9H3gJqq8nq2CkdpdLNVKBoxiCtkLfutdY4SQLtoY\n" + "USN7exk131pchsAJXYlR6mCW+ZP+E523cNwpPgsyKxVbmXSBAkEA9470fy2W0jFM\n" + "taZFslpntKSzbvn6JmdtjtvWrM1bBaeeqFiGBuQFYg46VaCUaeRWYw02jmYAsDYh\n" + "ZQavmXThaQJBAOHtlAQ0IJJEiMZr6vtVPH32fmbthSv1AUSYPzKqdlQrUnOXPQXu\n" + "z70cFoLG1TvPF5rBxbOkbQ/s8/ka5ZjPfdkCQCeC7YsO36+UpsWnUCBzRXITh4AC\n" + "7eYLQ/U1KUJTVF/GrQ/5cQrQgftwgecAxi9Qfmk4xqhbp2h4e0QAmS5I9WECQH02\n" + "0QwrX8nxFeTytr8pFGezj4a4KVCdb2B3CL+p3f70K7RIo9d/7b6frJI6ZL/LHQf2\n" + "UP4pKRDkgKsVDx7MELECQGm072/Z7vmb03h/uE95IYJOgY4nfmYs0QKA9Is18wUz\n" + "DpjfE33p0Ha6GO1VZRIQoqE24F8o5oimy3BEjryFuw4=\n" + "-----END RSA PRIVATE KEY-----\n") + + +cleartextCertificatePEM = ( + "-----BEGIN CERTIFICATE-----\n" + "MIICfTCCAeYCAQEwDQYJKoZIhvcNAQEEBQAwgYYxCzAJBgNVBAYTAlVTMRkwFwYD\n" + "VQQDExBweW9wZW5zc2wuc2YubmV0MREwDwYDVQQHEwhOZXcgWW9yazESMBAGA1UE\n" + "ChMJUHlPcGVuU1NMMREwDwYDVQQIEwhOZXcgWW9yazEQMA4GCSqGSIb3DQEJARYB\n" + "IDEQMA4GA1UECxMHVGVzdGluZzAeFw0wODAzMjUxOTA0MTNaFw0wOTAzMjUxOTA0\n" + "MTNaMIGGMQswCQYDVQQGEwJVUzEZMBcGA1UEAxMQcHlvcGVuc3NsLnNmLm5ldDER\n" + "MA8GA1UEBxMITmV3IFlvcmsxEjAQBgNVBAoTCVB5T3BlblNTTDERMA8GA1UECBMI\n" + "TmV3IFlvcmsxEDAOBgkqhkiG9w0BCQEWASAxEDAOBgNVBAsTB1Rlc3RpbmcwgZ8w\n" + "DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSwBsUWkXdqg6tnXy8H8hA1\n" + "msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nAE0zhmHJELcM8gUTIlXv/\n" + "cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXNxQn5ecR0UYSOWj6TTGXB\n" + "9VyUMQzCClcBAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAmm0Vzvv1O91WLl2LnF2P\n" + "q55LJdOnJbCCXIgxLdoVmvYAz1ZJq1eGKgKWI5QLgxiSzJLEU7KK//aVfiZzoCd5\n" + "RipBiEEMEV4eAY317bHPwPP+4Bj9t0l8AsDLseC5vLRHgxrLEu3bn08DYx6imB5Q\n" + "UBj849/xpszEM7BhwKE0GiQ=\n" + "-----END CERTIFICATE-----\n") + +count = count() +def go(): + port = socket() + port.bind(('', 0)) + port.listen(1) + + called = [] + def info(conn, where, ret): + print count.next() + called.append(None) + context = Context(TLSv1_METHOD) + context.set_info_callback(info) + context.use_certificate( + load_certificate(FILETYPE_PEM, cleartextCertificatePEM)) + context.use_privatekey( + load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)) + + while 1: + client = socket() + client.setblocking(False) + client.connect_ex(port.getsockname()) + + clientSSL = Connection(Context(TLSv1_METHOD), client) + clientSSL.set_connect_state() + + server, ignored = port.accept() + server.setblocking(False) + + serverSSL = Connection(context, server) + serverSSL.set_accept_state() + + del called[:] + while not called: + for ssl in clientSSL, serverSSL: + try: + ssl.do_handshake() + except WantReadError: + pass + + +threads = [Thread(target=go, args=()) for i in xrange(2)] +for th in threads: + th.start() +for th in threads: + th.join() |