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:
commit
611d86f302
4 changed files with 85 additions and 64 deletions
BIN
examples/puma/client-certs/keystore.jks
Normal file
BIN
examples/puma/client-certs/keystore.jks
Normal file
Binary file not shown.
BIN
examples/puma/client-certs/server.p12
Normal file
BIN
examples/puma/client-certs/server.p12
Normal file
Binary file not shown.
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue