org.littleshoot.proxy.extras.SelfSignedSslEngineSource Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of littleproxy Show documentation
Show all versions of littleproxy Show documentation
LittleProxy is a high performance HTTP proxy written in Java and using the Netty networking framework.
The newest version!
package org.littleshoot.proxy.extras;
import com.google.common.io.ByteStreams;
import org.littleshoot.proxy.SslEngineSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.Security;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
/**
* Basic {@link SslEngineSource} for testing. The {@link SSLContext} uses
* self-signed certificates that are generated lazily if the given key store
* file doesn't yet exist.
*/
public class SelfSignedSslEngineSource implements SslEngineSource {
private static final Logger LOG = LoggerFactory
.getLogger(SelfSignedSslEngineSource.class);
private static final String ALIAS = "littleproxy";
private static final String PASSWORD = "Be Your Own Lantern";
private static final String PROTOCOL = "TLS";
private final File keyStoreFile;
private final boolean trustAllServers;
private final boolean sendCerts;
private SSLContext sslContext;
public SelfSignedSslEngineSource(String keyStorePath,
boolean trustAllServers, boolean sendCerts) {
this.trustAllServers = trustAllServers;
this.sendCerts = sendCerts;
this.keyStoreFile = new File(keyStorePath);
initializeKeyStore();
initializeSSLContext();
}
public SelfSignedSslEngineSource(String keyStorePath) {
this(keyStorePath, false, true);
}
public SelfSignedSslEngineSource(boolean trustAllServers) {
this(trustAllServers, true);
}
public SelfSignedSslEngineSource(boolean trustAllServers, boolean sendCerts) {
this("littleproxy_keystore.jks", trustAllServers, sendCerts);
}
public SelfSignedSslEngineSource() {
this(false);
}
@Override
public SSLEngine newSslEngine() {
return sslContext.createSSLEngine();
}
@Override
public SSLEngine newSslEngine(String peerHost, int peerPort) {
return sslContext.createSSLEngine(peerHost, peerPort);
}
public SSLContext getSslContext() {
return sslContext;
}
private void initializeKeyStore() {
if (keyStoreFile.isFile()) {
LOG.info("Not deleting keystore");
return;
}
nativeCall("keytool", "-genkey", "-alias", ALIAS, "-keysize",
"4096", "-validity", "36500", "-keyalg", "RSA", "-dname",
"CN=littleproxy", "-keypass", PASSWORD, "-storepass",
PASSWORD, "-keystore", keyStoreFile.getName());
nativeCall("keytool", "-exportcert", "-alias", ALIAS, "-keystore",
keyStoreFile.getName(), "-storepass", PASSWORD, "-file",
"littleproxy_cert");
}
private void initializeSSLContext() {
String algorithm = Security
.getProperty("ssl.KeyManagerFactory.algorithm");
if (algorithm == null) {
algorithm = "SunX509";
}
try {
final KeyStore ks = KeyStore.getInstance("JKS");
// ks.load(new FileInputStream("keystore.jks"),
// "changeit".toCharArray());
ks.load(new FileInputStream(keyStoreFile), PASSWORD.toCharArray());
// Set up key manager factory to use our key store
final KeyManagerFactory kmf =
KeyManagerFactory.getInstance(algorithm);
kmf.init(ks, PASSWORD.toCharArray());
// Set up a trust manager factory to use our key store
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(algorithm);
tmf.init(ks);
TrustManager[] trustManagers = null;
if (!trustAllServers) {
trustManagers = tmf.getTrustManagers();
} else {
trustManagers = new TrustManager[] { new X509TrustManager() {
// TrustManager that trusts all servers
@Override
public void checkClientTrusted(X509Certificate[] arg0,
String arg1)
throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] arg0,
String arg1)
throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
} };
}
KeyManager[] keyManagers = null;
if (sendCerts) {
keyManagers = kmf.getKeyManagers();
} else {
keyManagers = new KeyManager[0];
}
// Initialize the SSLContext to work with our key managers.
sslContext = SSLContext.getInstance(PROTOCOL);
sslContext.init(keyManagers, trustManagers, null);
} catch (final Exception e) {
throw new Error(
"Failed to initialize the server-side SSLContext", e);
}
}
private String nativeCall(final String... commands) {
LOG.info("Running '{}'", Arrays.asList(commands));
final ProcessBuilder pb = new ProcessBuilder(commands);
try {
final Process process = pb.start();
final InputStream is = process.getInputStream();
byte[] data = ByteStreams.toByteArray(is);
String dataAsString = new String(data);
LOG.info("Completed native call: '{}'\nResponse: '" + dataAsString + "'",
Arrays.asList(commands));
return dataAsString;
} catch (final IOException e) {
LOG.error("Error running commands: " + Arrays.asList(commands), e);
return "";
}
}
}