[Jython-checkins] jython: Load default CA certs on Java 9 (#2390); and passing cert, key into engine
jim.baker
jython-checkins at python.org
Tue Dec 29 01:10:00 EST 2015
https://hg.python.org/jython/rev/5194b3d04dca
changeset: 7844:5194b3d04dca
user: Jim Baker <jim.baker at rackspace.com>
date: Mon Dec 28 23:09:56 2015 -0700
summary:
Load default CA certs on Java 9 (#2390); and passing cert, key into engine (#2437)
Java 9 has a slightly different layout of installed CA certs. Also now
passes cert and key files, if specified from the wrapping call, into
the underlying SSL engine.
files:
Lib/ssl.py | 32 +++++++++++++++++----------
Lib/test/test_ssl.py | 20 ++++++++++++++---
Lib/test/test_support.py | 5 ++++
3 files changed, 41 insertions(+), 16 deletions(-)
diff --git a/Lib/ssl.py b/Lib/ssl.py
--- a/Lib/ssl.py
+++ b/Lib/ssl.py
@@ -4,7 +4,7 @@
from java.security.cert import CertificateFactory
import uuid
from java.io import BufferedInputStream
-from java.security import KeyStore
+from java.security import KeyStore, KeyStoreException
from java.security.cert import CertificateParsingException
from javax.net.ssl import TrustManagerFactory
from javax.naming.ldap import LdapName
@@ -530,7 +530,9 @@
def setup_engine(self, addr):
if self.engine is None:
# http://stackoverflow.com/questions/13390964/java-ssl-fatal-error-80-unwrapping-net-record-after-adding-the-https-en
- self.engine = self._context._createSSLEngine(addr, self.server_hostname)
+ self.engine = self._context._createSSLEngine(
+ addr, self.server_hostname,
+ cert_file=getattr(self, "certfile", None), key_file=getattr(self, "keyfile", None))
self.engine.setUseClientMode(not self.server_side)
def connect(self, addr):
@@ -985,7 +987,7 @@
server_hostname=server_hostname,
_context=self)
- def _createSSLEngine(self, addr, hostname=None):
+ def _createSSLEngine(self, addr, hostname=None, cert_file=None, key_file=None):
trust_managers = [NoVerifyX509TrustManager()]
if self.verify_mode == CERT_REQUIRED:
tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
@@ -994,10 +996,15 @@
context = _JavaSSLContext.getInstance(self._protocol_name)
- if self._key_managers is None: # get an e
- context.init(_get_openssl_key_manager().getKeyManagers(), trust_managers, None)
+ if self._key_managers is None:
+ context.init(
+ _get_openssl_key_manager(
+ cert_file=cert_file, key_file=key_file).getKeyManagers(),
+ trust_managers, None)
else:
- context.init(self._key_managers.getKeyManagers(), trust_managers, None)
+ context.init(
+ self._key_managers.getKeyManagers(),
+ trust_managers, None)
if hostname is not None:
engine = context.createSSLEngine(hostname, addr[1])
@@ -1041,15 +1048,16 @@
if capath is not None:
for fname in os.listdir(capath):
_, ext = os.path.splitext(fname)
+ possible_cafile = os.path.join(capath, fname)
if ext.lower() == 'pem':
- cafiles.append(os.path.join(capath, fname))
+ cafiles.append(possible_cafile)
elif fname == 'cacerts': # java truststore
- if os.path.isfile(os.path.join(capath, fname)):
- cafiles.append(os.path.join(capath, fname))
- else:
- with open(os.path.join(capath, fname)) as f:
+ if os.path.isfile(possible_cafile):
+ cafiles.append(possible_cafile)
+ elif os.path.isfile(possible_cafile):
+ with open(possible_cafile) as f:
if PEM_HEADER in f.read():
- cafiles.append(os.path.join(capath, fname))
+ cafiles.append(possible_cafile)
certs = []
private_key = None
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -330,9 +330,15 @@
self.assertRaisesRegexp(ValueError,
"certfile must be specified for server-side operations",
ssl.wrap_socket, sock, server_side=True, certfile="")
- with closing(ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)) as s:
- self.assertRaisesRegexp(ValueError, "can't connect in server-side mode",
- s.connect, (HOST, 8080))
+ if support.get_java_version() < (1, 9):
+ # Possible FIXME similar issue as seen in
+ # test_load_cert_chain - apparently this RSA 1024 cert is too weak and gets a
+ # java.security.KeyStoreException: Key protection algorithm not found before the
+ # ValueError raised on earlier versions of Java;
+ # but we need to confirm this is truly the case on Java 9
+ with closing(ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)) as s:
+ self.assertRaisesRegexp(ValueError, "can't connect in server-side mode",
+ s.connect, (HOST, 8080))
with self.assertRaises(IOError) as cm:
with closing(socket.socket()) as sock:
ssl.wrap_socket(sock, certfile=WRONGCERT)
@@ -773,7 +779,13 @@
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
# Combined key and cert in a single file
ctx.load_cert_chain(CERTFILE, keyfile=None)
- ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
+ if support.get_java_version() < (1, 9):
+ # Possible FIXME we may be skipping this test on Java 9 unnecessarily.
+ # CERTFILE as generated uses RSA 1024, which is considered too weak.
+ # This may be why this raises an error on Java 9:
+ # java.security.KeyStoreException: Key protection algorithm not found:
+ # java.security.KeyStoreException: Certificate chain is not valid
+ ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
with self.assertRaises(IOError) as cm:
ctx.load_cert_chain(WRONGCERT)
diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py
--- a/Lib/test/test_support.py
+++ b/Lib/test/test_support.py
@@ -54,6 +54,11 @@
is_jython_nt = is_jython and (os._name == 'nt')
is_jython_posix = is_jython and (os._name == 'posix')
+if is_jython:
+ def get_java_version():
+ # returns (1, 9) for Java 9, etc
+ return tuple((int(x) for x in platform.java_ver()[0].split('.')[0:2]))
+
class Error(Exception):
"""Base class for regression test exceptions."""
--
Repository URL: https://hg.python.org/jython
More information about the Jython-checkins
mailing list