Skip to content

Commit

Permalink
JRuby - Add Puma::MiniSSL::Engine#init? and #teardown methods, run al…
Browse files Browse the repository at this point in the history
…l SSL tests (#2317)

Update MiniSSL.java and minissl.rb for JRuby

Add Puma::MiniSSL::Engine#init? and #teardown methods
  • Loading branch information
MSP-Greg committed Sep 1, 2020
1 parent 2710a6a commit fa6e916
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 9 deletions.
2 changes: 2 additions & 0 deletions History.md
@@ -1,5 +1,7 @@
### Master
* Bugfixes
* JRuby - Add Puma::MiniSSL::Engine#init? and #teardown methods, run all SSL tests (#2317)
* Improve shutdown reliability (#2312)
* Resolve issue with threadpool waiting counter decrement when thread is killed
* Constrain rake-compiler version to 0.9.4 to fix `ClassNotFound` exception when using MiniSSL with Java8.
* Ensure that TCP_CORK is usable
Expand Down
41 changes: 36 additions & 5 deletions ext/puma_http11/org/jruby/puma/MiniSSL.java
Expand Up @@ -120,6 +120,8 @@ public ByteList asByteList() {
}

private SSLEngine engine;
private boolean closed;
private boolean handshake;
private MiniSSLBuffer inboundNetData;
private MiniSSLBuffer outboundAppData;
private MiniSSLBuffer outboundNetData;
Expand Down Expand Up @@ -157,6 +159,8 @@ public IRubyObject initialize(ThreadContext threadContext, IRubyObject miniSSLCo
SSLContext sslCtx = SSLContext.getInstance("TLS");

sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
closed = false;
handshake = false;
engine = sslCtx.createSSLEngine();

String[] protocols;
Expand Down Expand Up @@ -240,14 +244,21 @@ private SSLEngineResult doOp(SSLOperation sslOp, MiniSSLBuffer src, MiniSSLBuffe
// need to wait for more data to come in before we retry
retryOp = false;
break;
case CLOSED:
closed = true;
retryOp = false;
break;
default:
// other cases are OK and CLOSED. We're done here.
// other case is OK. We're done here.
retryOp = false;
}
if (res.getHandshakeStatus() == HandshakeStatus.FINISHED) {
handshake = true;
}
}

// after each op, run any delegated tasks if needed
if(engine.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
if(res.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
Runnable runnable;
while ((runnable = engine.getDelegatedTask()) != null) {
runnable.run();
Expand All @@ -271,13 +282,14 @@ public IRubyObject read() throws Exception {

HandshakeStatus handshakeStatus = engine.getHandshakeStatus();
boolean done = false;
SSLEngineResult res = null;
while (!done) {
switch (handshakeStatus) {
case NEED_WRAP:
doOp(SSLOperation.WRAP, inboundAppData, outboundNetData);
res = doOp(SSLOperation.WRAP, inboundAppData, outboundNetData);
break;
case NEED_UNWRAP:
SSLEngineResult res = doOp(SSLOperation.UNWRAP, inboundNetData, inboundAppData);
res = doOp(SSLOperation.UNWRAP, inboundNetData, inboundAppData);
if (res.getStatus() == Status.BUFFER_UNDERFLOW) {
// need more data before we can shake more hands
done = true;
Expand All @@ -286,7 +298,9 @@ public IRubyObject read() throws Exception {
default:
done = true;
}
handshakeStatus = engine.getHandshakeStatus();
if (!done) {
handshakeStatus = res.getHandshakeStatus();
}
}

if (inboundNetData.hasRemaining()) {
Expand Down Expand Up @@ -360,4 +374,21 @@ public IRubyObject peercert() throws CertificateEncodingException {
return getRuntime().getNil();
}
}

@JRubyMethod(name = "init?")
public IRubyObject isInit(ThreadContext context) {
return handshake ? getRuntime().getFalse() : getRuntime().getTrue();
}

@JRubyMethod
public IRubyObject shutdown() {
if (closed || engine.isInboundDone() && engine.isOutboundDone()) {
if (engine.isOutboundDone()) {
engine.closeOutbound();
}
return getRuntime().getTrue();
} else {
return getRuntime().getFalse();
}
}
}
3 changes: 3 additions & 0 deletions lib/puma/minissl.rb
Expand Up @@ -197,6 +197,9 @@ def peercert
end

if IS_JRUBY
OPENSSL_NO_SSL3 = false
OPENSSL_NO_TLS1 = false

class SSLError < StandardError
# Define this for jruby even though it isn't used.
end
Expand Down
15 changes: 11 additions & 4 deletions test/test_puma_server_ssl.rb
Expand Up @@ -23,10 +23,17 @@ def ssl_error(error, peeraddr, peercert)
Puma::MiniSSL.check
# net/http (loaded in helper) does not necessarily load OpenSSL
require "openssl" unless Object.const_defined? :OpenSSL
puts "", RUBY_DESCRIPTION, "RUBYOPT: #{ENV['RUBYOPT']}",
" Puma::MiniSSL OpenSSL",
"OPENSSL_LIBRARY_VERSION: #{Puma::MiniSSL::OPENSSL_LIBRARY_VERSION.ljust 32}#{OpenSSL::OPENSSL_LIBRARY_VERSION}",
" OPENSSL_VERSION: #{Puma::MiniSSL::OPENSSL_VERSION.ljust 32}#{OpenSSL::OPENSSL_VERSION}", ""
if Puma::IS_JRUBY
puts "", RUBY_DESCRIPTION, "RUBYOPT: #{ENV['RUBYOPT']}",
" OpenSSL",
"OPENSSL_LIBRARY_VERSION: #{OpenSSL::OPENSSL_LIBRARY_VERSION}",
" OPENSSL_VERSION: #{OpenSSL::OPENSSL_VERSION}", ""
else
puts "", RUBY_DESCRIPTION, "RUBYOPT: #{ENV['RUBYOPT']}",
" Puma::MiniSSL OpenSSL",
"OPENSSL_LIBRARY_VERSION: #{Puma::MiniSSL::OPENSSL_LIBRARY_VERSION.ljust 32}#{OpenSSL::OPENSSL_LIBRARY_VERSION}",
" OPENSSL_VERSION: #{Puma::MiniSSL::OPENSSL_VERSION.ljust 32}#{OpenSSL::OPENSSL_VERSION}", ""
end
rescue
true
else
Expand Down

0 comments on commit fa6e916

Please sign in to comment.