Skip to content

Commit

Permalink
Fix support for certain proxies. Set nodelay and keepalive. Add optio…
Browse files Browse the repository at this point in the history
…n trust all certs.
  • Loading branch information
hollingsworthd committed Dec 2, 2015
1 parent 3b7d0b2 commit 3ca72ac
Showing 1 changed file with 77 additions and 55 deletions.
132 changes: 77 additions & 55 deletions src/com/machinepublishers/jbrowserdriver/StreamConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@
import java.nio.file.Paths;
import java.security.KeyStore;
import java.security.Permission;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collection;
Expand All @@ -68,6 +70,7 @@

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
Expand All @@ -86,12 +89,14 @@
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.cache.CachingHttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.ssl.TrustStrategy;

class StreamConnection extends HttpURLConnection implements Closeable {
private static final Pattern invalidUrlChar = Pattern.compile("[^-A-Za-z0-9._~:/?#\\[\\]@!$&'()*+,;=]");
Expand Down Expand Up @@ -121,6 +126,7 @@ class StreamConnection extends HttpURLConnection implements Closeable {
.setMaxConnPerRoute(ROUTE_CONNECTIONS)
.setMaxConnTotal(CONNECTIONS)
.setDefaultCredentialsProvider(ProxyAuth.instance())
.setConnectionReuseStrategy(DefaultConnectionReuseStrategy.INSTANCE)
.build();
private static final CloseableHttpClient cachingClient = CachingHttpClients.custom()
.disableRedirectHandling()
Expand All @@ -129,6 +135,7 @@ class StreamConnection extends HttpURLConnection implements Closeable {
.setMaxConnPerRoute(ROUTE_CONNECTIONS)
.setMaxConnTotal(CONNECTIONS)
.setDefaultCredentialsProvider(ProxyAuth.instance())
.setConnectionReuseStrategy(DefaultConnectionReuseStrategy.INSTANCE)
.build();
private static boolean cacheByDefault;

Expand Down Expand Up @@ -171,56 +178,70 @@ class StreamConnection extends HttpURLConnection implements Closeable {
}

private static SSLContext sslContext() {
//a good pem source: https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt
if (System.getProperty("jbd.pemfile") != null) {
try {
String location = System.getProperty("jbd.pemfile");
File cachedPemFile = new File("./pemfile_cached");
boolean remote = location.startsWith("https://") || location.startsWith("http://");
if (remote && cachedPemFile.exists()
&& (System.currentTimeMillis() - cachedPemFile.lastModified() < 48 * 60 * 60 * 1000)) {
location = cachedPemFile.getAbsolutePath();
remote = false;
}
String pemBlocks = null;
if (remote) {
HttpURLConnection remotePemFile = (HttpURLConnection) new URL(location).openConnection();
remotePemFile.setRequestMethod("GET");
remotePemFile.connect();
pemBlocks = Util.toString(remotePemFile.getInputStream(),
Util.charset(remotePemFile));
cachedPemFile.delete();
Files.write(Paths.get(cachedPemFile.getAbsolutePath()), pemBlocks.getBytes("utf-8"));
} else {
pemBlocks = new String(Files.readAllBytes(
Paths.get(new File(location).getAbsolutePath())), "utf-8");
if ("trustanything".equals(System.getProperty("jbd.pemfile"))) {
try {
return SSLContexts.custom().loadTrustMaterial(KeyStore.getInstance(KeyStore.getDefaultType()),
new TrustStrategy() {
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
}).build();
} catch (Throwable t) {
Logs.logsFor(1l).exception(t);
}
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Matcher matcher = pemBlock.matcher(pemBlocks);
boolean found = false;
while (matcher.find()) {
String pemBlock = matcher.group(1).replaceAll("[\\n\\r]+", "");
ByteArrayInputStream byteStream = new ByteArrayInputStream(Base64.getDecoder().decode(pemBlock));
java.security.cert.X509Certificate cert = (java.security.cert.X509Certificate) cf.generateCertificate(byteStream);
String alias = cert.getSubjectX500Principal().getName("RFC2253");
if (alias != null && !keyStore.containsAlias(alias)) {
found = true;
keyStore.setCertificateEntry(alias, cert);
} else {
try {
String location = System.getProperty("jbd.pemfile");
location = location.equals("compatible")
? "https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt" : location;
File cachedPemFile = new File("./pemfile_cached");
boolean remote = location.startsWith("https://") || location.startsWith("http://");
if (remote && cachedPemFile.exists()
&& (System.currentTimeMillis() - cachedPemFile.lastModified() < 48 * 60 * 60 * 1000)) {
location = cachedPemFile.getAbsolutePath();
remote = false;
}
String pemBlocks = null;
if (remote) {
HttpURLConnection remotePemFile = (HttpURLConnection) new URL(location).openConnection();
remotePemFile.setRequestMethod("GET");
remotePemFile.connect();
pemBlocks = Util.toString(remotePemFile.getInputStream(),
Util.charset(remotePemFile));
cachedPemFile.delete();
Files.write(Paths.get(cachedPemFile.getAbsolutePath()), pemBlocks.getBytes("utf-8"));
} else {
pemBlocks = new String(Files.readAllBytes(
Paths.get(new File(location).getAbsolutePath())), "utf-8");
}
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Matcher matcher = pemBlock.matcher(pemBlocks);
boolean found = false;
while (matcher.find()) {
String pemBlock = matcher.group(1).replaceAll("[\\n\\r]+", "");
ByteArrayInputStream byteStream = new ByteArrayInputStream(Base64.getDecoder().decode(pemBlock));
java.security.cert.X509Certificate cert = (java.security.cert.X509Certificate) cf.generateCertificate(byteStream);
String alias = cert.getSubjectX500Principal().getName("RFC2253");
if (alias != null && !keyStore.containsAlias(alias)) {
found = true;
keyStore.setCertificateEntry(alias, cert);
}
}
if (found) {
KeyManagerFactory keyManager = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManager.init(keyStore, null);
TrustManagerFactory trustManager = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManager.init(keyStore);
SSLContext context = SSLContext.getInstance("TLS");
context.init(keyManager.getKeyManagers(), trustManager.getTrustManagers(), null);
return context;
}
} catch (Throwable t) {
Logs.logsFor(1l).exception(t);
}
if (found) {
KeyManagerFactory keyManager = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManager.init(keyStore, null);
TrustManagerFactory trustManager = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManager.init(keyStore);
SSLContext context = SSLContext.getInstance("TLS");
context.init(keyManager.getKeyManagers(), trustManager.getTrustManagers(), null);
return context;
}
} catch (Throwable t) {
Logs.logsFor(1l).exception(t);
}
}
return SSLContexts.createSystemDefault();
Expand All @@ -244,15 +265,17 @@ public Socket createSocket(final HttpContext context) throws IOException {
}
}

private static Socket newSocket(final HttpContext context) {
private static Socket newSocket(final HttpContext context) throws IOException {
InetSocketAddress proxySocks = (InetSocketAddress) context.getAttribute("proxy.socks.address");
InetSocketAddress proxyHttp = (InetSocketAddress) context.getAttribute("proxy.http.address");
Socket socket;
if (proxySocks != null) {
return new Socket(new Proxy(Proxy.Type.SOCKS, proxySocks));
} else if (proxyHttp != null) {
return new Socket(new Proxy(Proxy.Type.HTTP, proxyHttp));
socket = new Socket(new Proxy(Proxy.Type.SOCKS, proxySocks));
} else {
socket = new Socket();
}
return new Socket();
socket.setTcpNoDelay(true);
socket.setKeepAlive(true);
return socket;
}

private boolean isBlocked(String host) {
Expand Down Expand Up @@ -375,7 +398,7 @@ public void connect() throws IOException {
if (proxy.type() == ProxyConfig.Type.SOCKS) {
context.setAttribute("proxy.socks.address", proxyAddress);
} else {
context.setAttribute("proxy.http.address", proxyAddress);
config.setProxy(new HttpHost(proxy.host(), proxy.port()));
}
}
context.setCookieStore(SettingsManager.get(settingsId.get()).get().cookieStore());
Expand Down Expand Up @@ -480,8 +503,7 @@ public String getResponseMessage() throws IOException {
@Override
public int getResponseCode() throws IOException {
exec();
StatusMonitor.get(settingsId.get()).addRedirect(
urlString, getHeaderField("location"));
StatusMonitor.get(settingsId.get()).addRedirect(urlString, getHeaderField("location"));
if (skip.get()) {
return 204;
}
Expand Down

0 comments on commit 3ca72ac

Please sign in to comment.