| # Copyright (C) Jean-Paul Calderone |
| # See LICENSE for details. |
| # |
| # 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() |