mirror of
https://github.com/puma/puma.git
synced 2022-11-09 13:48:40 -05:00
Start java version of MiniSSL
This commit is contained in:
parent
d7ff3888c0
commit
e191003fc4
4 changed files with 185 additions and 0 deletions
6
Rakefile
6
Rakefile
|
@ -60,6 +60,8 @@ file 'ext/puma_http11/org/jruby/puma/Http11Parser.java' => ['ext/puma_http11/htt
|
|||
end
|
||||
task :ragel => ['ext/puma_http11/org/jruby/puma/Http11Parser.java']
|
||||
|
||||
if !IS_JRUBY
|
||||
|
||||
# compile extensions using rake-compiler
|
||||
# C (MRI, Rubinius)
|
||||
Rake::ExtensionTask.new("puma_http11", HOE.spec) do |ext|
|
||||
|
@ -77,11 +79,15 @@ Rake::ExtensionTask.new("puma_http11", HOE.spec) do |ext|
|
|||
CLEAN.include "lib/puma/puma_http11.rb"
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
# Java (JRuby)
|
||||
Rake::JavaExtensionTask.new("puma_http11", HOE.spec) do |ext|
|
||||
ext.lib_dir = "lib/puma"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# the following is a fat-binary stub that will be used when
|
||||
# require 'puma/puma_http11' and will use either 1.8 or 1.9 version depending
|
||||
# on RUBY_VERSION
|
||||
|
|
|
@ -6,10 +6,12 @@ import org.jruby.Ruby;
|
|||
import org.jruby.runtime.load.BasicLibraryService;
|
||||
|
||||
import org.jruby.puma.Http11;
|
||||
import org.jruby.puma.MiniSSL;
|
||||
|
||||
public class PumaHttp11Service implements BasicLibraryService {
|
||||
public boolean basicLoad(final Ruby runtime) throws IOException {
|
||||
Http11.createHttp11(runtime);
|
||||
MiniSSL.createMiniSSL(runtime);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
169
ext/puma_http11/org/jruby/puma/MiniSSL.java
Normal file
169
ext/puma_http11/org/jruby/puma/MiniSSL.java
Normal file
|
@ -0,0 +1,169 @@
|
|||
package org.jruby.puma;
|
||||
|
||||
import org.jruby.Ruby;
|
||||
import org.jruby.RubyClass;
|
||||
import org.jruby.RubyHash;
|
||||
import org.jruby.RubyModule;
|
||||
import org.jruby.RubyNumeric;
|
||||
import org.jruby.RubyObject;
|
||||
import org.jruby.RubyString;
|
||||
|
||||
import org.jruby.anno.JRubyMethod;
|
||||
|
||||
import org.jruby.runtime.ObjectAllocator;
|
||||
import org.jruby.runtime.ThreadContext;
|
||||
import org.jruby.runtime.builtin.IRubyObject;
|
||||
|
||||
import org.jruby.exceptions.RaiseException;
|
||||
|
||||
import org.jruby.util.ByteList;
|
||||
|
||||
|
||||
import javax.net.ssl.*;
|
||||
import javax.net.ssl.SSLEngineResult.*;
|
||||
import java.io.*;
|
||||
import java.security.*;
|
||||
import java.nio.*;
|
||||
|
||||
public class MiniSSL extends RubyObject {
|
||||
private static ObjectAllocator ALLOCATOR = new ObjectAllocator() {
|
||||
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
|
||||
return new MiniSSL(runtime, klass);
|
||||
}
|
||||
};
|
||||
|
||||
public static void createMiniSSL(Ruby runtime) {
|
||||
RubyModule mPuma = runtime.defineModule("Puma");
|
||||
RubyModule ssl = mPuma.defineModuleUnder("MiniSSL");
|
||||
|
||||
mPuma.defineClassUnder("SSLError",
|
||||
runtime.getClass("IOError"),
|
||||
runtime.getClass("IOError").getAllocator());
|
||||
|
||||
RubyClass eng = ssl.defineClassUnder("Engine",runtime.getObject(),ALLOCATOR);
|
||||
eng.defineAnnotatedMethods(MiniSSL.class);
|
||||
}
|
||||
|
||||
private Ruby runtime;
|
||||
private SSLContext sslc;
|
||||
|
||||
private SSLEngine engine;
|
||||
|
||||
private ByteBuffer peerAppData;
|
||||
private ByteBuffer peerNetData;
|
||||
private ByteBuffer netData;
|
||||
private ByteBuffer dummy;
|
||||
|
||||
public MiniSSL(Ruby runtime, RubyClass klass) {
|
||||
super(runtime, klass);
|
||||
|
||||
this.runtime = runtime;
|
||||
}
|
||||
|
||||
@JRubyMethod
|
||||
public IRubyObject initialize(IRubyObject key, IRubyObject cert)
|
||||
throws java.security.KeyStoreException,
|
||||
java.io.FileNotFoundException,
|
||||
java.io.IOException,
|
||||
java.io.FileNotFoundException,
|
||||
java.security.NoSuchAlgorithmException,
|
||||
java.security.KeyManagementException,
|
||||
java.security.cert.CertificateException,
|
||||
java.security.UnrecoverableKeyException
|
||||
{
|
||||
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
|
||||
ks.load(new FileInputStream(key.convertToString().asJavaString()), null);
|
||||
ts.load(new FileInputStream(cert.convertToString().asJavaString()), null);
|
||||
|
||||
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
|
||||
kmf.init(ks, null);
|
||||
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
|
||||
tmf.init(ts);
|
||||
|
||||
SSLContext sslCtx = SSLContext.getInstance("TLS");
|
||||
|
||||
sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
|
||||
|
||||
sslc = sslCtx;
|
||||
|
||||
engine = sslc.createSSLEngine();
|
||||
engine.setUseClientMode(false);
|
||||
// engine.setNeedClientAuth(true);
|
||||
|
||||
SSLSession session = engine.getSession();
|
||||
peerNetData = ByteBuffer.allocate(session.getPacketBufferSize());
|
||||
peerAppData = ByteBuffer.allocate(session.getApplicationBufferSize());
|
||||
netData = ByteBuffer.allocate(session.getPacketBufferSize());
|
||||
peerNetData.limit(0);
|
||||
peerAppData.limit(0);
|
||||
netData.limit(0);
|
||||
dummy = ByteBuffer.allocate(0);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@JRubyMethod
|
||||
public IRubyObject inject(IRubyObject arg) {
|
||||
peerNetData.put(arg.convertToString().getBytes());
|
||||
return this;
|
||||
}
|
||||
|
||||
@JRubyMethod
|
||||
public IRubyObject read() throws javax.net.ssl.SSLException {
|
||||
peerAppData.clear();
|
||||
peerNetData.flip();
|
||||
SSLEngineResult res;
|
||||
|
||||
do {
|
||||
res = engine.unwrap(peerNetData, peerAppData);
|
||||
} while(res.getStatus() == SSLEngineResult.Status.OK &&
|
||||
res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_UNWRAP &&
|
||||
res.bytesProduced() == 0);
|
||||
|
||||
if(peerAppData.position() == 0 &&
|
||||
res.getStatus() == SSLEngineResult.Status.OK &&
|
||||
peerNetData.hasRemaining()) {
|
||||
res = engine.unwrap(peerNetData, peerAppData);
|
||||
}
|
||||
|
||||
peerNetData.compact();
|
||||
peerAppData.flip();
|
||||
|
||||
byte[] bss = new byte[peerAppData.limit()];
|
||||
|
||||
peerAppData.get(bss);
|
||||
|
||||
RubyString str = getRuntime().newString("");
|
||||
str.setValue(new ByteList(bss));
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
@JRubyMethod
|
||||
public IRubyObject write(IRubyObject arg) throws javax.net.ssl.SSLException {
|
||||
byte[] bls = arg.convertToString().getBytes();
|
||||
ByteBuffer src = ByteBuffer.wrap(bls);
|
||||
|
||||
SSLEngineResult res = engine.wrap(src, netData);
|
||||
|
||||
return getRuntime().newFixnum(res.bytesConsumed());
|
||||
}
|
||||
|
||||
@JRubyMethod
|
||||
public IRubyObject extract() {
|
||||
netData.flip();
|
||||
|
||||
byte[] bss = new byte[netData.limit()];
|
||||
|
||||
netData.get(bss);
|
||||
netData.clear();
|
||||
|
||||
RubyString str = getRuntime().newString("");
|
||||
str.setValue(new ByteList(bss));
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
|
@ -83,6 +83,14 @@ module Puma::MiniSSL
|
|||
VERIFY_NONE = 0
|
||||
VERIFY_PEER = 1
|
||||
|
||||
if defined?(JRUBY_VERSION)
|
||||
class Engine
|
||||
def self.server(key, cert)
|
||||
new(key, cert)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Server
|
||||
def initialize(socket, ctx)
|
||||
@socket = socket
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue