Author: Richard Plangger <[email protected]>
Branch: py3.5-ssl
Changeset: r88427:742c85b008ab
Date: 2016-11-17 10:05 +0100
http://bitbucket.org/pypy/pypy/changeset/742c85b008ab/
Log: copy over certificates of cpython stdlib (ssl + ssl_tests) target
3.5.2
diff --git a/lib-python/3/test/capath/0e4015b9.0
b/lib-python/3/test/capath/0e4015b9.0
new file mode 100644
--- /dev/null
+++ b/lib-python/3/test/capath/0e4015b9.0
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIIClTCCAf6gAwIBAgIJAKGU95wKR8pTMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV
+BAYTAlhZMRcwFQYDVQQHDA5DYXN0bGUgQW50aHJheDEjMCEGA1UECgwaUHl0aG9u
+IFNvZnR3YXJlIEZvdW5kYXRpb24xIzAhBgNVBAMMGnNlbGYtc2lnbmVkLnB5dGhv
+bnRlc3QubmV0MB4XDTE0MTEwMjE4MDkyOVoXDTI0MTAzMDE4MDkyOVowcDELMAkG
+A1UEBhMCWFkxFzAVBgNVBAcMDkNhc3RsZSBBbnRocmF4MSMwIQYDVQQKDBpQeXRo
+b24gU29mdHdhcmUgRm91bmRhdGlvbjEjMCEGA1UEAwwac2VsZi1zaWduZWQucHl0
+aG9udGVzdC5uZXQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANDXQXW9tjyZ
+Xt0Iv2tLL1+jinr4wGg36ioLDLFkMf+2Y1GL0v0BnKYG4N1OKlAU15LXGeGer8vm
+Sv/yIvmdrELvhAbbo3w4a9TMYQA4XkIVLdvu3mvNOAet+8PMJxn26dbDhG809ALv
+EHY57lQsBS3G59RZyBPVqAqmImWNJnVzAgMBAAGjNzA1MCUGA1UdEQQeMByCGnNl
+bGYtc2lnbmVkLnB5dGhvbnRlc3QubmV0MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN
+AQEFBQADgYEAIuzAhgMouJpNdf3URCHIineyoSt6WK/9+eyUcjlKOrDoXNZaD72h
+TXMeKYoWvJyVcSLKL8ckPtDobgP2OTt0UkyAaj0n+ZHaqq1lH2yVfGUA1ILJv515
+C8BqbvVZuqm3i7ygmw3bqE/lYMgOrYtXXnqOrz6nvsE6Yc9V9rFflOM=
+-----END CERTIFICATE-----
diff --git a/lib-python/3/test/capath/ce7b8643.0
b/lib-python/3/test/capath/ce7b8643.0
new file mode 100644
--- /dev/null
+++ b/lib-python/3/test/capath/ce7b8643.0
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIIClTCCAf6gAwIBAgIJAKGU95wKR8pTMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV
+BAYTAlhZMRcwFQYDVQQHDA5DYXN0bGUgQW50aHJheDEjMCEGA1UECgwaUHl0aG9u
+IFNvZnR3YXJlIEZvdW5kYXRpb24xIzAhBgNVBAMMGnNlbGYtc2lnbmVkLnB5dGhv
+bnRlc3QubmV0MB4XDTE0MTEwMjE4MDkyOVoXDTI0MTAzMDE4MDkyOVowcDELMAkG
+A1UEBhMCWFkxFzAVBgNVBAcMDkNhc3RsZSBBbnRocmF4MSMwIQYDVQQKDBpQeXRo
+b24gU29mdHdhcmUgRm91bmRhdGlvbjEjMCEGA1UEAwwac2VsZi1zaWduZWQucHl0
+aG9udGVzdC5uZXQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANDXQXW9tjyZ
+Xt0Iv2tLL1+jinr4wGg36ioLDLFkMf+2Y1GL0v0BnKYG4N1OKlAU15LXGeGer8vm
+Sv/yIvmdrELvhAbbo3w4a9TMYQA4XkIVLdvu3mvNOAet+8PMJxn26dbDhG809ALv
+EHY57lQsBS3G59RZyBPVqAqmImWNJnVzAgMBAAGjNzA1MCUGA1UdEQQeMByCGnNl
+bGYtc2lnbmVkLnB5dGhvbnRlc3QubmV0MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN
+AQEFBQADgYEAIuzAhgMouJpNdf3URCHIineyoSt6WK/9+eyUcjlKOrDoXNZaD72h
+TXMeKYoWvJyVcSLKL8ckPtDobgP2OTt0UkyAaj0n+ZHaqq1lH2yVfGUA1ILJv515
+C8BqbvVZuqm3i7ygmw3bqE/lYMgOrYtXXnqOrz6nvsE6Yc9V9rFflOM=
+-----END CERTIFICATE-----
diff --git a/lib-python/3/test/selfsigned_pythontestdotnet.pem
b/lib-python/3/test/selfsigned_pythontestdotnet.pem
--- a/lib-python/3/test/selfsigned_pythontestdotnet.pem
+++ b/lib-python/3/test/selfsigned_pythontestdotnet.pem
@@ -1,5 +1,5 @@
-----BEGIN CERTIFICATE-----
-MIIChzCCAfCgAwIBAgIJAKGU95wKR8pSMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV
+MIIClTCCAf6gAwIBAgIJAKGU95wKR8pTMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV
BAYTAlhZMRcwFQYDVQQHDA5DYXN0bGUgQW50aHJheDEjMCEGA1UECgwaUHl0aG9u
IFNvZnR3YXJlIEZvdW5kYXRpb24xIzAhBgNVBAMMGnNlbGYtc2lnbmVkLnB5dGhv
bnRlc3QubmV0MB4XDTE0MTEwMjE4MDkyOVoXDTI0MTAzMDE4MDkyOVowcDELMAkG
@@ -8,9 +8,9 @@
aG9udGVzdC5uZXQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANDXQXW9tjyZ
Xt0Iv2tLL1+jinr4wGg36ioLDLFkMf+2Y1GL0v0BnKYG4N1OKlAU15LXGeGer8vm
Sv/yIvmdrELvhAbbo3w4a9TMYQA4XkIVLdvu3mvNOAet+8PMJxn26dbDhG809ALv
-EHY57lQsBS3G59RZyBPVqAqmImWNJnVzAgMBAAGjKTAnMCUGA1UdEQQeMByCGnNl
-bGYtc2lnbmVkLnB5dGhvbnRlc3QubmV0MA0GCSqGSIb3DQEBBQUAA4GBAIOXmdtM
-eG9qzP9TiXW/Gc/zI4cBfdCpC+Y4gOfC9bQUC7hefix4iO3+iZjgy3X/FaRxUUoV
-HKiXcXIaWqTSUWp45cSh0MbwZXudp6JIAptzdAhvvCrPKeC9i9GvxsPD4LtDAL97
-vSaxQBezA7hdxZd90/EeyMgVZgAnTCnvAWX9
+EHY57lQsBS3G59RZyBPVqAqmImWNJnVzAgMBAAGjNzA1MCUGA1UdEQQeMByCGnNl
+bGYtc2lnbmVkLnB5dGhvbnRlc3QubmV0MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN
+AQEFBQADgYEAIuzAhgMouJpNdf3URCHIineyoSt6WK/9+eyUcjlKOrDoXNZaD72h
+TXMeKYoWvJyVcSLKL8ckPtDobgP2OTt0UkyAaj0n+ZHaqq1lH2yVfGUA1ILJv515
+C8BqbvVZuqm3i7ygmw3bqE/lYMgOrYtXXnqOrz6nvsE6Yc9V9rFflOM=
-----END CERTIFICATE-----
diff --git a/lib-python/3/test/test_ssl.py b/lib-python/3/test/test_ssl.py
--- a/lib-python/3/test/test_ssl.py
+++ b/lib-python/3/test/test_ssl.py
@@ -23,9 +23,6 @@
PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
HOST = support.HOST
-IS_LIBRESSL = ssl.OPENSSL_VERSION.startswith('LibreSSL')
-IS_OPENSSL_1_1 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0)
-
def data_file(*name):
return os.path.join(os.path.dirname(__file__), *name)
@@ -57,8 +54,6 @@
SIGNED_CERTFILE = data_file("keycert3.pem")
SIGNED_CERTFILE2 = data_file("keycert4.pem")
SIGNING_CA = data_file("pycacert.pem")
-# cert with all kinds of subject alt names
-ALLSANFILE = data_file("allsans.pem")
REMOTE_HOST = "self-signed.pythontest.net"
REMOTE_ROOT_CERT = data_file("selfsigned_pythontestdotnet.pem")
@@ -148,8 +143,8 @@
def test_str_for_enums(self):
# Make sure that the PROTOCOL_* constants have enum-like string
# reprs.
- proto = ssl.PROTOCOL_TLS
- self.assertEqual(str(proto), '_SSLMethod.PROTOCOL_TLS')
+ proto = ssl.PROTOCOL_SSLv23
+ self.assertEqual(str(proto), '_SSLMethod.PROTOCOL_SSLv23')
ctx = ssl.SSLContext(proto)
self.assertIs(ctx.protocol, proto)
@@ -281,27 +276,6 @@
self.assertEqual(p['subjectAltName'], san)
- def test_parse_all_sans(self):
- p = ssl._ssl._test_decode_cert(ALLSANFILE)
- self.assertEqual(p['subjectAltName'],
- (
- ('DNS', 'allsans'),
- ('othername', '<unsupported>'),
- ('othername', '<unsupported>'),
- ('email', '[email protected]'),
- ('DNS', 'www.example.org'),
- ('DirName',
- ((('countryName', 'XY'),),
- (('localityName', 'Castle Anthrax'),),
- (('organizationName', 'Python Software Foundation'),),
- (('commonName', 'dirname example'),))),
- ('URI', 'https://www.python.org/'),
- ('IP Address', '127.0.0.1'),
- ('IP Address', '0:0:0:0:0:0:0:1\n'),
- ('Registered ID', '1.2.3.4.5')
- )
- )
-
def test_DER_to_PEM(self):
with open(CAFILE_CACERT, 'r') as f:
pem = f.read()
@@ -338,8 +312,8 @@
self.assertGreaterEqual(status, 0)
self.assertLessEqual(status, 15)
# Version string as returned by {Open,Libre}SSL, the format might
change
- if IS_LIBRESSL:
- self.assertTrue(s.startswith("LibreSSL {:d}".format(major)),
+ if "LibreSSL" in s:
+ self.assertTrue(s.startswith("LibreSSL {:d}.{:d}".format(major,
minor)),
(s, t, hex(n)))
else:
self.assertTrue(s.startswith("OpenSSL
{:d}.{:d}.{:d}".format(major, minor, fix)),
@@ -816,8 +790,7 @@
def test_constructor(self):
for protocol in PROTOCOLS:
ssl.SSLContext(protocol)
- ctx = ssl.SSLContext()
- self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
+ self.assertRaises(TypeError, ssl.SSLContext)
self.assertRaises(ValueError, ssl.SSLContext, -1)
self.assertRaises(ValueError, ssl.SSLContext, 42)
@@ -838,15 +811,15 @@
def test_options(self):
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
# OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
- default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
- if not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0):
- default |= ssl.OP_NO_COMPRESSION
- self.assertEqual(default, ctx.options)
+ self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
+ ctx.options)
ctx.options |= ssl.OP_NO_TLSv1
- self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
+ self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 |
ssl.OP_NO_TLSv1,
+ ctx.options)
if can_clear_options():
- ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
- self.assertEqual(default, ctx.options)
+ ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
+ self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
+ ctx.options)
ctx.options = 0
# Ubuntu has OP_NO_SSLv3 forced on by default
self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
@@ -1182,7 +1155,6 @@
self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
@unittest.skipIf(sys.platform == "win32", "not-Windows specific")
- @unittest.skipIf(IS_LIBRESSL, "LibreSSL doesn't support env vars")
def test_load_default_certs_env(self):
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
with support.EnvironmentVarGuard() as env:
@@ -1778,13 +1750,13 @@
sslobj = ctx.wrap_bio(incoming, outgoing, False, REMOTE_HOST)
self.assertIs(sslobj._sslobj.owner, sslobj)
self.assertIsNone(sslobj.cipher())
- self.assertIsNotNone(sslobj.shared_ciphers())
+ self.assertIsNone(sslobj.shared_ciphers())
self.assertRaises(ValueError, sslobj.getpeercert)
if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
self.assertTrue(sslobj.cipher())
- self.assertIsNotNone(sslobj.shared_ciphers())
+ self.assertIsNone(sslobj.shared_ciphers())
self.assertTrue(sslobj.getpeercert())
if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
self.assertTrue(sslobj.get_channel_binding('tls-unique'))
@@ -1898,14 +1870,7 @@
else:
self.sock.close()
- # PyPy change
def run(self):
- try:
- self._run()
- finally:
- self.close()
-
- def _run(self):
self.running = True
if not self.server.starttls_server:
if not self.wrap_conn():
@@ -2668,7 +2633,7 @@
s.close()
def test_socketserver(self):
- """Using socketserver to create and manage SSL connections."""
+ """Using a SocketServer to create and manage SSL connections."""
server = make_https_server(self, certfile=CERTFILE)
# try to connect
if support.verbose:
@@ -2695,6 +2660,8 @@
def test_asyncore_server(self):
"""Check the example asyncore integration."""
+ indata = "TEST MESSAGE of mixed case\n"
+
if support.verbose:
sys.stdout.write("\n")
@@ -2826,13 +2793,20 @@
# consume data
s.read()
+ data = b"data"
+
# read(-1, buffer) is supported, even though read(-1) is not
- data = b"data"
s.send(data)
buffer = bytearray(len(data))
self.assertEqual(s.read(-1, buffer), len(data))
self.assertEqual(buffer, data)
+ # recv/read(0) should return no data
+ s.send(data)
+ self.assertEqual(s.recv(0), b"")
+ self.assertEqual(s.read(0), b"")
+ self.assertEqual(s.read(), data)
+
# Make sure sendmsg et al are disallowed to avoid
# inadvertent disclosure of data and/or corruption
# of the encrypted data stream
@@ -2848,26 +2822,6 @@
s.close()
- def test_recv_zero(self):
- server = ThreadedEchoServer(CERTFILE)
- server.__enter__()
- self.addCleanup(server.__exit__, None, None)
- s = socket.create_connection((HOST, server.port))
- self.addCleanup(s.close)
- s = ssl.wrap_socket(s, suppress_ragged_eofs=False)
- self.addCleanup(s.close)
-
- # recv/read(0) should return no data
- s.send(b"data")
- self.assertEqual(s.recv(0), b"")
- self.assertEqual(s.read(0), b"")
- self.assertEqual(s.read(), b"data")
-
- # Should not block if the other end sends no data
- s.setblocking(False)
- self.assertEqual(s.recv(0), b"")
- self.assertEqual(s.recv_into(bytearray()), 0)
-
def test_nonblocking_send(self):
server = ThreadedEchoServer(CERTFILE,
certreqs=ssl.CERT_NONE,
@@ -2889,10 +2843,8 @@
# will be full and the call will block
buf = bytearray(8192)
def fill_buffer():
- i = 0
while True:
s.send(buf)
- i += 1
self.assertRaises((ssl.SSLWantWriteError,
ssl.SSLWantReadError), fill_buffer)
@@ -3028,7 +2980,7 @@
with context.wrap_socket(socket.socket()) as s:
self.assertIs(s.version(), None)
s.connect((HOST, server.port))
- self.assertEqual(s.version(), 'TLSv1')
+ self.assertEqual(s.version(), "TLSv1")
self.assertIs(s.version(), None)
@unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled
OpenSSL")
@@ -3170,36 +3122,24 @@
(['http/3.0', 'http/4.0'], None)
]
for client_protocols, expected in protocol_tests:
- server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
+ server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
server_context.load_cert_chain(CERTFILE)
server_context.set_alpn_protocols(server_protocols)
- client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
+ client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
client_context.load_cert_chain(CERTFILE)
client_context.set_alpn_protocols(client_protocols)
-
- try:
- stats = server_params_test(client_context,
- server_context,
- chatty=True,
- connectionchatty=True)
- except ssl.SSLError as e:
- stats = e
-
- if expected is None and IS_OPENSSL_1_1:
- # OpenSSL 1.1.0 raises handshake error
- self.assertIsInstance(stats, ssl.SSLError)
- else:
- msg = "failed trying %s (s) and %s (c).\n" \
- "was expecting %s, but got %%s from the %%s" \
- % (str(server_protocols), str(client_protocols),
- str(expected))
- client_result = stats['client_alpn_protocol']
- self.assertEqual(client_result, expected,
- msg % (client_result, "client"))
- server_result = stats['server_alpn_protocols'][-1] \
- if len(stats['server_alpn_protocols']) else 'nothing'
- self.assertEqual(server_result, expected,
- msg % (server_result, "server"))
+ stats = server_params_test(client_context, server_context,
+ chatty=True, connectionchatty=True)
+
+ msg = "failed trying %s (s) and %s (c).\n" \
+ "was expecting %s, but got %%s from the %%s" \
+ % (str(server_protocols), str(client_protocols),
+ str(expected))
+ client_result = stats['client_alpn_protocol']
+ self.assertEqual(client_result, expected, msg %
(client_result, "client"))
+ server_result = stats['server_alpn_protocols'][-1] \
+ if len(stats['server_alpn_protocols']) else 'nothing'
+ self.assertEqual(server_result, expected, msg %
(server_result, "server"))
def test_selected_npn_protocol(self):
# selected_npn_protocol() is None unless NPN is used
@@ -3347,23 +3287,13 @@
client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
client_context.verify_mode = ssl.CERT_REQUIRED
client_context.load_verify_locations(SIGNING_CA)
- if ssl.OPENSSL_VERSION_INFO >= (1, 0, 2):
- client_context.set_ciphers("AES128:AES256")
- server_context.set_ciphers("AES256")
- alg1 = "AES256"
- alg2 = "AES-256"
- else:
- client_context.set_ciphers("AES:3DES")
- server_context.set_ciphers("3DES")
- alg1 = "3DES"
- alg2 = "DES-CBC3"
-
+ client_context.set_ciphers("RC4")
+ server_context.set_ciphers("AES:RC4")
stats = server_params_test(client_context, server_context)
ciphers = stats['server_shared_ciphers'][0]
self.assertGreater(len(ciphers), 0)
for name, tls_version, bits in ciphers:
- if not alg1 in name.split("-") and alg2 not in name:
- self.fail(name)
+ self.assertIn("RC4", name.split("-"))
def test_read_write_after_close_raises_valuerror(self):
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
diff --git a/lib_pypy/openssl/_cffi_src/openssl/err.py
b/lib_pypy/openssl/_cffi_src/openssl/err.py
--- a/lib_pypy/openssl/_cffi_src/openssl/err.py
+++ b/lib_pypy/openssl/_cffi_src/openssl/err.py
@@ -196,9 +196,34 @@
static const int SSL_TLSEXT_ERR_ALERT_FATAL;
static const int SSL_TLSEXT_ERR_NOACK;
+static const int SSL_AD_CLOSE_NOTIFY;
+static const int SSL_AD_UNEXPECTED_MESSAGE;
+static const int SSL_AD_BAD_RECORD_MAC;
+static const int SSL_AD_RECORD_OVERFLOW;
+static const int SSL_AD_DECOMPRESSION_FAILURE;
+static const int SSL_AD_HANDSHAKE_FAILURE;
+static const int SSL_AD_BAD_CERTIFICATE;
+static const int SSL_AD_UNSUPPORTED_CERTIFICATE;
+static const int SSL_AD_CERTIFICATE_REVOKED;
+static const int SSL_AD_CERTIFICATE_EXPIRED;
+static const int SSL_AD_CERTIFICATE_UNKNOWN;
+static const int SSL_AD_ILLEGAL_PARAMETER;
+static const int SSL_AD_UNKNOWN_CA;
+static const int SSL_AD_ACCESS_DENIED;
+static const int SSL_AD_DECODE_ERROR;
+static const int SSL_AD_DECRYPT_ERROR;
+static const int SSL_AD_PROTOCOL_VERSION;
+static const int SSL_AD_INSUFFICIENT_SECURITY;
static const int SSL_AD_INTERNAL_ERROR;
-static const int SSL_AD_ACCESS_DENIED;
-static const int SSL_AD_HANDSHAKE_FAILURE;
+static const int SSL_AD_USER_CANCELLED;
+static const int SSL_AD_NO_RENEGOTIATION;
+
+static const int SSL_AD_UNSUPPORTED_EXTENSION;
+static const int SSL_AD_CERTIFICATE_UNOBTAINABLE;
+static const int SSL_AD_UNRECOGNIZED_NAME;
+static const int SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
+static const int SSL_AD_BAD_CERTIFICATE_HASH_VALUE;
+static const int SSL_AD_UNKNOWN_PSK_IDENTITY;
"""
FUNCTIONS = """
@@ -255,4 +280,24 @@
static const long Cryptography_HAS_RSA_R_PKCS_DECODING_ERROR = 0;
static const long RSA_R_PKCS_DECODING_ERROR = 0;
#endif
+
+#ifndef SSL_AD_UNSUPPORTED_EXTENSION
+ static const int SSL_AD_UNSUPPORTED_EXTENSION = -1;
+#endif
+#ifndef SSL_AD_CERTIFICATE_UNOBTAINABLE
+ static const int SSL_AD_CERTIFICATE_UNOBTAINABLE = -1;
+#endif
+#ifndef SSL_AD_UNRECOGNIZED_NAME
+ static const int SSL_AD_UNRECOGNIZED_NAME = -1;
+#endif
+#ifndef SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE
+ static const int SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE = -1;
+#endif
+#ifndef SSL_AD_BAD_CERTIFICATE_HASH_VALUE
+ static const int SSL_AD_BAD_CERTIFICATE_HASH_VALUE = -1;
+#endif
+#ifndef SSL_AD_UNKNOWN_PSK_IDENTITY
+ static const int SSL_AD_UNKNOWN_PSK_IDENTITY = -1;
+#endif
+
"""
diff --git a/lib_pypy/openssl/_cffi_src/openssl/ssl.py
b/lib_pypy/openssl/_cffi_src/openssl/ssl.py
--- a/lib_pypy/openssl/_cffi_src/openssl/ssl.py
+++ b/lib_pypy/openssl/_cffi_src/openssl/ssl.py
@@ -695,9 +695,9 @@
static const long Cryptography_HAS_SSL_CTX_CLEAR_OPTIONS = 1;
#ifdef OPENSSL_NO_TLSEXT
+static const long Cryptography_NO_TLSEXT = 1;
+#else
static const long Cryptography_NO_TLSEXT = 0;
-#else
-static const long Cryptography_NO_TLSEXT = 1;
#endif
#ifdef OPENSSL_NPN_NEGOTIATED
diff --git a/lib_pypy/openssl/_stdssl/__init__.py
b/lib_pypy/openssl/_stdssl/__init__.py
--- a/lib_pypy/openssl/_stdssl/__init__.py
+++ b/lib_pypy/openssl/_stdssl/__init__.py
@@ -8,7 +8,7 @@
from openssl._stdssl.certificate import (_test_decode_cert,
_decode_certificate, _certificate_to_der)
from openssl._stdssl.utility import (_str_with_len, _bytes_with_len,
- _str_to_ffi_buffer, _str_from_buf)
+ _str_to_ffi_buffer, _str_from_buf, _cstr_decode_fs)
from openssl._stdssl.error import (ssl_error, pyssl_error,
SSLError, SSLZeroReturnError, SSLWantReadError,
SSLWantWriteError, SSLSyscallError,
@@ -17,8 +17,9 @@
SSL_ERROR_SSL, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE,
SSL_ERROR_WANT_X509_LOOKUP, SSL_ERROR_SYSCALL,
SSL_ERROR_ZERO_RETURN, SSL_ERROR_WANT_CONNECT,
- SSL_ERROR_EOF, SSL_ERROR_NO_SOCKET, SSL_ERROR_INVALID_ERROR_CODE)
-
+ SSL_ERROR_EOF, SSL_ERROR_NO_SOCKET, SSL_ERROR_INVALID_ERROR_CODE,
+ pyerr_write_unraisable)
+from openssl._stdssl import error
OPENSSL_VERSION = ffi.string(lib.OPENSSL_VERSION_TEXT).decode('utf-8')
OPENSSL_VERSION_NUMBER = lib.OPENSSL_VERSION_NUMBER
@@ -85,6 +86,12 @@
else:
CHANNEL_BINDING_TYPES = []
+for name in error.SSL_AD_NAMES:
+ lib_attr = 'SSL_AD_' + name
+ attr = 'ALERT_DESCRIPTION_' + name
+ if hasattr(lib, lib_attr):
+ globals()[attr] = getattr(lib, lib_attr)
+
# init open ssl
lib.SSL_load_error_strings()
lib.SSL_library_init()
@@ -103,6 +110,7 @@
callable = None
password = None
operationerror = None
+ handle = None
PWINFO_STORAGE = {}
def _Cryptography_pem_password_cb(buf, size, rwflag, userdata):
@@ -258,8 +266,8 @@
self._owner = None
self.server_hostname = None
self.socket = None
- self.alpn_protocols = ffi.NULL
- self.npn_protocols = ffi.NULL
+ #self.alpn_protocols = ffi.NULL
+ #self.npn_protocols = ffi.NULL
@property
def owner(self):
@@ -710,7 +718,7 @@
class _SSLContext(object):
__slots__ = ('ctx', '_check_hostname', 'servername_callback',
'alpn_protocols', 'npn_protocols', 'set_hostname',
- '_set_hostname_handle')
+ '_set_hostname_handle', '_npn_protocols_handle')
def __new__(cls, protocol):
self = object.__new__(cls)
@@ -861,8 +869,6 @@
pw_info = PasswordInfo()
index = -1
if password is not None:
- index = _thread.get_ident()
- PWINFO_STORAGE[index] = pw_info
if callable(password):
pw_info.callable = password
@@ -872,9 +878,11 @@
else:
raise TypeError("password should be a string or callable")
- handle = ffi.new_handle(pw_info) # XXX MUST NOT be garbage
collected
+ pw_info.handle = ffi.new_handle(pw_info)
+ index = _thread.get_ident()
+ PWINFO_STORAGE[index] = pw_info
lib.SSL_CTX_set_default_passwd_cb(self.ctx,
Cryptography_pem_password_cb)
- lib.SSL_CTX_set_default_passwd_cb_userdata(self.ctx, handle)
+ lib.SSL_CTX_set_default_passwd_cb_userdata(self.ctx,
pw_info.handle)
try:
ffi.errno = 0
@@ -908,7 +916,7 @@
ret = lib.SSL_CTX_check_private_key(self.ctx)
if ret != 1:
- raise _ssl_seterror(None, -1)
+ raise ssl_error(None)
finally:
if index >= 0:
del PWINFO_STORAGE[index]
@@ -1033,6 +1041,7 @@
return {'x509': x509, 'x509_ca': x509_ca, 'crl': crl}
+# REVIEW, how to do that properly
# def _finalize_(self):
# ctx = self.ctx
# if ctx:
@@ -1125,8 +1134,8 @@
return
if not callable(callback):
raise TypeError("not a callable object")
- self.set_hostname = callback
- self._set_hostname_handle = ffi.new_handle(self)
+ scb = ServernameCallback(callback, self)
+ self._set_hostname_handle = ffi.new_handle(scb)
lib.Cryptography_SSL_CTX_set_tlsext_servername_callback(self.ctx,
_servername_callback)
lib.Cryptography_SSL_CTX_set_tlsext_servername_arg(self.ctx,
self._set_hostname_handle)
@@ -1146,6 +1155,7 @@
if HAS_NPN:
self.npn_protocols = ffi.from_buffer(protos)
handle = ffi.new_handle(self)
+ self._npn_protocols_handle = handle # track a reference to the
handle
lib.SSL_CTX_set_next_protos_advertised_cb(self.ctx,
advertise_npn_callback, handle)
lib.SSL_CTX_set_next_proto_select_cb(self.ctx,
select_npn_callback, handle)
else:
@@ -1156,20 +1166,21 @@
if HAS_SNI and not lib.Cryptography_NO_TLSEXT:
@ffi.callback("int(SSL*,int*,void*)")
def _servername_callback(s, al, arg):
- ssl_ctx = ffi.from_handle(arg)
+ scb = ffi.from_handle(arg)
+ ssl_ctx = scb.ctx
servername = lib.SSL_get_servername(s, lib.TLSEXT_NAMETYPE_host_name)
- #ifdef WITH_THREAD
- # TODO PyGILState_STATE gstate = PyGILState_Ensure();
- #endif
+ set_hostname = scb.callback
+ #ifdef WITH_THREAD
+ # TODO PyGILState_STATE gstate = PyGILState_Ensure();
+ #endif
- if ssl_ctx.set_hostname is None:
+ if set_hostname is None:
#/* remove race condition in this the call back while if removing
the
# * callback is in progress */
- #ifdef WITH_THREAD
- # TODO PyGILState_Release(gstate);
- #endif
+ #ifdef WITH_THREAD
+ # TODO PyGILState_Release(gstate);
+ #endif
return lib.SSL_TLSEXT_ERR_OK
- #}
ssl = ffi.from_handle(lib.SSL_get_app_data(s))
assert isinstance(ssl, _SSLSocket)
@@ -1192,10 +1203,9 @@
if servername == ffi.NULL:
try:
- result = ssl_ctx.set_hostname(ssl_socket, None, ssl_ctx)
- except:
- # TODO
- # PyErr_WriteUnraisable(ssl_ctx->set_hostname);
+ result = set_hostname(ssl_socket, None, ssl_ctx)
+ except Exception as e:
+ pyerr_write_unraisable(e, set_hostname)
al[0] = lib.SSL_AD_HANDSHAKE_FAILURE
return lib.SSL_TLSEXT_ERR_ALERT_FATAL
else:
@@ -1203,31 +1213,44 @@
try:
servername_idna = servername.decode("idna")
- except UnicodeDecodeError:
- raise # TODO?
- # PyErr_WriteUnraisable(servername_o);
+ except UnicodeDecodeError as e:
+ pyerr_write_unraisable(e, servername)
try:
- result = ssl_ctx.set_hostname(ssl_socket, servername_idna,
ssl_ctx)
- except:
- # TODO
- # PyErr_WriteUnraisable(ssl_ctx->set_hostname);
+ result = set_hostname(ssl_socket, servername_idna, ssl_ctx)
+ except Exception as e:
+ pyerr_write_unraisable(e, set_hostname)
al[0] = lib.SSL_AD_HANDSHAKE_FAILURE
return lib.SSL_TLSEXT_ERR_ALERT_FATAL
if result is not None:
+ # this is just a poor man's emulation:
+ # in CPython this works a bit different, it calls all the way
+ # down from PyLong_AsLong to _PyLong_FromNbInt which raises
+ # a TypeError if there is no nb_int slot filled.
try:
- al[0] = int(result)
- except:
- # PyErr_WriteUnraisable(result);
- al[0] = lib.SSL_AD_INTERNAL_ERROR
- return lib.SSL_TLSEXT_ERR_ALERT_FATAL
+ if isinstance(result, int):
+ al[0] = result
+ else:
+ if result is not None:
+ if hasattr(result,'__int__'):
+ al[0] = result.__int__()
+ return lib.SSL_TLSEXT_ERR_ALERT_FATAL
+ # needed because sys.exec_info is used in
pyerr_write_unraisable
+ raise TypeError("an integer is required (got type %s)" %
result)
+ except TypeError as e:
+ pyerr_write_unraisable(e, result)
+ al[0] = lib.SSL_AD_INTERNAL_ERROR
+ return lib.SSL_TLSEXT_ERR_ALERT_FATAL
else:
# TODO gil state release?
return lib.SSL_TLSEXT_ERR_OK
class ServernameCallback(object):
- ctx = None
+ def __init__(self, callback, ctx):
+ self.callback = callback
+ self.ctx = ctx
+
SERVERNAME_CALLBACKS = weakref.WeakValueDictionary()
TEST = None
@@ -1287,13 +1310,13 @@
"""Whether the memory BIO is at EOF."""
return lib.BIO_ctrl_pending(self.bio) == 0 and self.eof_written
- def write(self, _bytes):
+ def write(self, strlike):
INT_MAX = 2**31-1
- if isinstance(_bytes, memoryview):
- # REVIEW pypy does not support from_buffer of a memoryview
- # copies the data!
- _bytes = bytes(_bytes)
- buf = ffi.from_buffer(_bytes)
+ if isinstance(strlike, memoryview):
+ # FIXME pypy must support get_raw_address for
+ # StringBuffer to remove this case!
+ strlike = strlike.tobytes()
+ buf = ffi.from_buffer(strlike)
if len(buf) > INT_MAX:
raise OverflowError("string longer than %d bytes", INT_MAX)
@@ -1346,7 +1369,7 @@
ok = lib.RAND_bytes(buf, count)
if ok == 1:
return ffi.string(buf)
- raise ssl_error("", errcode=lib.ERR_get_error())
+ raise ssl_error(None, errcode=lib.ERR_get_error())
def RAND_pseudo_bytes(count):
return _RAND_bytes(count, True)
@@ -1358,19 +1381,6 @@
buf = _str_to_ffi_buffer(view)
lib.RAND_add(buf, len(buf), entropy)
-
-def _cstr_decode_fs(buf):
-#define CONVERT(info, target) { \
-# const char *tmp = (info); \
-# target = NULL; \
-# if (!tmp) { Py_INCREF(Py_None); target = Py_None; } \
-# else if ((target = PyUnicode_DecodeFSDefault(tmp)) == NULL) { \
-# target = PyBytes_FromString(tmp); } \
-# if (!target) goto error; \
-# }
- # REVIEW
- return ffi.string(buf).decode(sys.getfilesystemencoding())
-
def get_default_verify_paths():
ofile_env = _cstr_decode_fs(lib.X509_get_default_cert_file_env())
@@ -1385,7 +1395,6 @@
odir = _cstr_decode_fs(lib.X509_get_default_cert_dir())
if odir is None:
return odir
-
return (ofile_env, ofile, odir_env, odir);
@ffi.callback("int(SSL*,unsigned char **,unsigned char *,const unsigned char
*,unsigned int,void *)")
@@ -1395,28 +1404,28 @@
ffi.cast("unsigned
char*",ctx.alpn_protocols), len(ctx.alpn_protocols),
client_protocols, client_protocols_len)
[email protected]("int(SSL*,unsigned char **,unsigned char *,const unsigned char
*,unsigned int,void *)")
-def select_npn_callback(ssl, out, outlen, server_protocols,
server_protocols_len, args):
- ctx = ffi.from_handle(args)
- return do_protocol_selection(0, out, outlen, server_protocols,
server_protocols_len,
- ffi.cast("unsigned char*",ctx.npn_protocols),
len(ctx.npn_protocols))
+if lib.Cryptography_HAS_NPN_NEGOTIATED:
+ @ffi.callback("int(SSL*,unsigned char **,unsigned char *,const unsigned
char *,unsigned int,void *)")
+ def select_npn_callback(ssl, out, outlen, server_protocols,
server_protocols_len, args):
+ ctx = ffi.from_handle(args)
+ return do_protocol_selection(0, out, outlen, server_protocols,
server_protocols_len,
+ ffi.cast("unsigned
char*",ctx.npn_protocols), len(ctx.npn_protocols))
[email protected]("int(SSL*,const unsigned char**, unsigned int*, void*)")
-def advertise_npn_callback(ssl, data, length, args):
- ctx = ffi.from_handle(args)
+ @ffi.callback("int(SSL*,const unsigned char**, unsigned int*, void*)")
+ def advertise_npn_callback(ssl, data, length, args):
+ ctx = ffi.from_handle(args)
- if not ctx.npn_protocols:
- data[0] = ffi.new("unsigned char*", b"")
- length[0] = 0
- else:
- data[0] = ffi.cast("unsigned char*",ctx.npn_protocols)
- length[0] = len(ctx.npn_protocols)
+ if not ctx.npn_protocols:
+ data[0] = ffi.new("unsigned char*", b"")
+ length[0] = 0
+ else:
+ data[0] = ffi.cast("unsigned char*",ctx.npn_protocols)
+ length[0] = len(ctx.npn_protocols)
- return lib.SSL_TLSEXT_ERR_OK
+ return lib.SSL_TLSEXT_ERR_OK
-if lib.Cryptography_HAS_NPN_NEGOTIATED:
def do_protocol_selection(alpn, out, outlen, server_protocols,
server_protocols_len,
client_protocols,
client_protocols_len):
if client_protocols == ffi.NULL:
diff --git a/lib_pypy/openssl/_stdssl/error.py
b/lib_pypy/openssl/_stdssl/error.py
--- a/lib_pypy/openssl/_stdssl/error.py
+++ b/lib_pypy/openssl/_stdssl/error.py
@@ -1,3 +1,5 @@
+import sys
+import traceback
from _openssl import ffi
from _openssl import lib
@@ -46,7 +48,7 @@
if errstr is None:
errcode = lib.ERR_peek_last_error()
try:
- return fill_sslerror(SSLError, errcode, errstr)
+ return fill_sslerror(SSLError, errcode, errstr, errcode)
finally:
lib.ERR_clear_error()
@@ -136,6 +138,7 @@
lib_str = LIB_CODES_TO_NAMES.get(err_lib, None)
if errstr is None:
errstr = _str_from_buf(lib.ERR_reason_error_string(errcode))
+ msg = errstr
if not errstr:
msg = "unknown error"
if reason_str and lib_str:
@@ -148,3 +151,49 @@
err_value.library = lib_str if lib_str else None
return err_value
+def pyerr_write_unraisable(exc, obj):
+ f = sys.stderr
+
+ if obj:
+ f.write("Exception ignored in: ")
+ f.write(repr(obj))
+ f.write("\n")
+
+ t, v, tb = sys.exc_info()
+ traceback.print_tb(tb, file=f)
+
+ assert isinstance(v, Exception)
+ f.write(t.__module__ + "." + t.__name__)
+ f.write(": ")
+ f.write(str(v))
+ f.write("\n")
+
+SSL_AD_NAMES = [
+ "ACCESS_DENIED",
+ "BAD_CERTIFICATE",
+ "BAD_CERTIFICATE_HASH_VALUE",
+ "BAD_CERTIFICATE_STATUS_RESPONSE",
+ "BAD_RECORD_MAC",
+ "CERTIFICATE_EXPIRED",
+ "CERTIFICATE_REVOKED",
+ "CERTIFICATE_UNKNOWN",
+ "CERTIFICATE_UNOBTAINABLE",
+ "CLOSE_NOTIFY",
+ "DECODE_ERROR",
+ "DECOMPRESSION_FAILURE",
+ "DECRYPT_ERROR",
+ "HANDSHAKE_FAILURE",
+ "ILLEGAL_PARAMETER",
+ "INSUFFICIENT_SECURITY",
+ "INTERNAL_ERROR",
+ "NO_RENEGOTIATION",
+ "PROTOCOL_VERSION",
+ "RECORD_OVERFLOW",
+ "UNEXPECTED_MESSAGE",
+ "UNKNOWN_CA",
+ "UNKNOWN_PSK_IDENTITY",
+ "UNRECOGNIZED_NAME",
+ "UNSUPPORTED_CERTIFICATE",
+ "UNSUPPORTED_EXTENSION",
+ "USER_CANCELLED",
+]
diff --git a/lib_pypy/openssl/_stdssl/utility.py
b/lib_pypy/openssl/_stdssl/utility.py
--- a/lib_pypy/openssl/_stdssl/utility.py
+++ b/lib_pypy/openssl/_stdssl/utility.py
@@ -1,3 +1,4 @@
+import sys
from _openssl import ffi
from _openssl import lib
@@ -36,3 +37,15 @@
def _str_from_buf(buf):
return ffi.string(buf).decode('utf-8')
+def _cstr_decode_fs(buf):
+#define CONVERT(info, target) { \
+# const char *tmp = (info); \
+# target = NULL; \
+# if (!tmp) { Py_INCREF(Py_None); target = Py_None; } \
+# else if ((target = PyUnicode_DecodeFSDefault(tmp)) == NULL) { \
+# target = PyBytes_FromString(tmp); } \
+# if (!target) goto error; \
+# }
+ # REVIEW
+ return ffi.string(buf).decode(sys.getfilesystemencoding())
+
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit