diff --git a/src/main/java/org/jruby/ext/openssl/BCSSLSupport.java b/src/main/java/org/jruby/ext/openssl/BCSSLSupport.java index d8fc6f16..8782afb8 100644 --- a/src/main/java/org/jruby/ext/openssl/BCSSLSupport.java +++ b/src/main/java/org/jruby/ext/openssl/BCSSLSupport.java @@ -46,8 +46,16 @@ static SSLSession getBCSession(final SSLEngine engine) { static boolean setBCSessionToResume(final SSLEngine engine, final SSLSession session) { if (engine instanceof BCSSLEngine && session instanceof BCExtendedSSLSession) { - ((BCSSLEngine) engine).setBCSessionToResume((BCExtendedSSLSession) session); - return true; + try { + ((BCSSLEngine) engine).setBCSessionToResume((BCExtendedSSLSession) session); + return true; + } catch (IllegalArgumentException e) { + // This can happen when a Java gem's post-install hook (e.g. fast-rsa-engine) + // downloads BC JARs via Maven and loads them under a new classloader. At that + // point there are two copies of BC in the JVM, and ProvSSLEngine rejects the + // stored session because it came from a different classloader context. + // Just fall through and let the caller do a fresh handshake. + } } return false; } diff --git a/src/main/java/org/jruby/ext/openssl/SSLSocket.java b/src/main/java/org/jruby/ext/openssl/SSLSocket.java index 6a6ecc66..b65e0233 100644 --- a/src/main/java/org/jruby/ext/openssl/SSLSocket.java +++ b/src/main/java/org/jruby/ext/openssl/SSLSocket.java @@ -1356,10 +1356,12 @@ private void tryResumeSessionIfSet(final ThreadContext context) { if (BCSSLSupport.setBCSessionToResume(engine, setSession.sslSession())) return; - // can not support this without the (BC) SSL provider internals (e.g. on SunJSSE) - // but we can assume setting a session= is meant to be a *forced* session re-use: + // Without BC internals (e.g. on SunJSSE) we can't force session re-use. + // We used to call setEnableSessionCreation(false) here to signal that intent, + // but that backfires: if the stored session can't be resumed for any reason + // (including the BC classloader mismatch above), BC-JSSE throws instead of + // falling back to a fresh handshake. Leave session creation enabled. if (reusableSSLEngine()) { - engine.setEnableSessionCreation(false); final SSLSession session = getSession(context.runtime); if (!setSession.equals(session)) { session.set_timeout(context, setSession.timeout(context));