org.littleshoot.proxy.extras.SelfSignedSslEngineSource Maven / Gradle / Ivy
package org.littleshoot.proxy.extras;
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;
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 org.apache.commons.io.IOUtils;
import org.littleshoot.proxy.SslEngineSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 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();
final String data = IOUtils.toString(is);
LOG.info("Completed native call: '{}'\nResponse: '" + data + "'",
Arrays.asList(commands));
return data;
} catch (final IOException e) {
LOG.error("Error running commands: " + Arrays.asList(commands), e);
return "";
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy