summaryrefslogtreecommitdiff
path: root/leakcheck
diff options
context:
space:
mode:
authorJean-Paul Calderone <exarkun@boson>2008-04-26 19:06:28 -0400
committerJean-Paul Calderone <exarkun@boson>2008-04-26 19:06:28 -0400
commit5ef8651eb21d0712ffdd237d107fdc6a98bd4ca7 (patch)
treea01ee59c43e9206dde4e0bc6bb0b7b1ad6c25a10 /leakcheck
parent828c9cbbe7cf89e5e7e62f9d0ac29a6293a3165c (diff)
downloadpyopenssl-5ef8651eb21d0712ffdd237d107fdc6a98bd4ca7.tar.gz
Fix a threading bug in the info callback support for context objects.
Also add some tests for Context.set_info_callback.
Diffstat (limited to 'leakcheck')
-rw-r--r--leakcheck/context-info-callback.py96
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()