1
0
Fork 0
mirror of https://github.com/puma/puma.git synced 2022-11-09 13:48:40 -05:00

Merge pull request #833 from joemiller/jruby-client-tls-auth

support TLS client auth (verify_mode) in jruby
This commit is contained in:
Evan Phoenix 2016-01-27 19:44:01 -08:00
commit 611d86f302
4 changed files with 85 additions and 64 deletions

Binary file not shown.

Binary file not shown.

View file

@ -13,6 +13,7 @@ import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
@ -136,23 +137,36 @@ public class MiniSSL extends RubyObject {
public IRubyObject initialize(ThreadContext threadContext, IRubyObject miniSSLContext)
throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
char[] password = miniSSLContext.callMethod(threadContext, "keystore_pass").convertToString().asJavaString().toCharArray();
ks.load(new FileInputStream(miniSSLContext.callMethod(threadContext, "keystore").convertToString().asJavaString()),
password);
String keystoreFile = miniSSLContext.callMethod(threadContext, "keystore").convertToString().asJavaString();
ks.load(new FileInputStream(keystoreFile), password);
ts.load(new FileInputStream(keystoreFile), password);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, password);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ts);
SSLContext sslCtx = SSLContext.getInstance("TLS");
sslCtx.init(kmf.getKeyManagers(), null, null);
sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
engine = sslCtx.createSSLEngine();
String[] protocols = new String[] { "TLSv1", "TLSv1.1", "TLSv1.2" };
engine.setEnabledProtocols(protocols);
engine.setUseClientMode(false);
long verify_mode = miniSSLContext.callMethod(threadContext, "verify_mode").convertToInteger().getLongValue();
if ((verify_mode & 0x1) != 0) { // 'peer'
engine.setWantClientAuth(true);
}
if ((verify_mode & 0x2) != 0) { // 'force_peer'
engine.setNeedClientAuth(true);
}
SSLSession session = engine.getSession();
inboundNetData = new MiniSSLBuffer(session.getPacketBufferSize());
outboundAppData = new MiniSSLBuffer(session.getApplicationBufferSize());

View file

@ -132,7 +132,6 @@ class TestPumaServerSSL < Test::Unit::TestCase
end
# client-side TLS authentication tests
unless defined?(JRUBY_VERSION)
class TestPumaServerSSLClient < Test::Unit::TestCase
def assert_ssl_client_error_match(error, subject=nil, &blk)
@ -142,9 +141,14 @@ unless defined?(JRUBY_VERSION)
@app = lambda { |env| [200, {}, [env['rack.url_scheme']]] }
@ctx = Puma::MiniSSL::Context.new
if defined?(JRUBY_VERSION)
@ctx.keystore = File.expand_path "../../examples/puma/client-certs/keystore.jks", __FILE__
@ctx.keystore_pass = 'blahblah'
else
@ctx.key = File.expand_path "../../examples/puma/client-certs/server.key", __FILE__
@ctx.cert = File.expand_path "../../examples/puma/client-certs/server.crt", __FILE__
@ctx.ca = File.expand_path "../../examples/puma/client-certs/ca.crt", __FILE__
end
@ctx.verify_mode = Puma::MiniSSL::VERIFY_PEER | Puma::MiniSSL::VERIFY_FAIL_IF_NO_PEER_CERT
events = SSLEventsHelper.new STDOUT, STDERR
@ -170,9 +174,13 @@ unless defined?(JRUBY_VERSION)
sleep 0.1
assert_equal !!error, client_error
# The JRuby MiniSSL implementation lacks error capturing currently, so we can't inspect the
# messages here
unless defined?(JRUBY_VERSION)
assert_match error, events.error.message if error
assert_equal @host, events.addr if error
assert_equal subject, events.cert.subject.to_s if subject
end
ensure
@server.stop(true)
end
@ -220,4 +228,3 @@ unless defined?(JRUBY_VERSION)
end
end
end
end