• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.jsoup.integration;
2 
3 import org.eclipse.jetty.http.HttpVersion;
4 import org.eclipse.jetty.server.Connector;
5 import org.eclipse.jetty.server.HttpConfiguration;
6 import org.eclipse.jetty.server.HttpConnectionFactory;
7 import org.eclipse.jetty.server.SecureRequestCustomizer;
8 import org.eclipse.jetty.server.Server;
9 import org.eclipse.jetty.server.ServerConnector;
10 import org.eclipse.jetty.server.SslConnectionFactory;
11 import org.eclipse.jetty.server.handler.HandlerWrapper;
12 import org.eclipse.jetty.servlet.FilterHolder;
13 import org.eclipse.jetty.servlet.FilterMapping;
14 import org.eclipse.jetty.servlet.ServletHandler;
15 import org.eclipse.jetty.util.ssl.SslContextFactory;
16 import org.jsoup.integration.servlets.AuthFilter;
17 import org.jsoup.integration.servlets.BaseServlet;
18 import org.jsoup.integration.servlets.ProxyServlet;
19 
20 import javax.net.ssl.HttpsURLConnection;
21 import javax.net.ssl.SSLContext;
22 import javax.net.ssl.SSLSocketFactory;
23 import javax.net.ssl.TrustManager;
24 import javax.net.ssl.TrustManagerFactory;
25 import java.io.File;
26 import java.io.FileNotFoundException;
27 import java.io.IOException;
28 import java.net.InetSocketAddress;
29 import java.nio.file.Files;
30 import java.security.KeyManagementException;
31 import java.security.KeyStore;
32 import java.security.KeyStoreException;
33 import java.security.NoSuchAlgorithmException;
34 import java.security.cert.CertificateException;
35 import java.util.concurrent.atomic.AtomicInteger;
36 
37 public class TestServer {
38     static int Port;
39     static int TlsPort;
40 
41     private static final String Localhost = "localhost";
42     private static final String KeystorePassword = "hunter2";
43 
44     private static final Server Jetty = newServer();
45     private static final ServletHandler JettyHandler = new ServletHandler();
46     private static final Server Proxy = newServer();
47     private static final Server AuthedProxy = newServer();
48     private static final HandlerWrapper ProxyHandler = new HandlerWrapper();
49     private static final HandlerWrapper AuthedProxyHandler = new HandlerWrapper();
50     private static final ProxySettings ProxySettings = new ProxySettings();
51 
newServer()52     private static Server newServer() {
53         return new Server(new InetSocketAddress(Localhost, 0));
54     }
55 
56     static {
57         Jetty.setHandler(JettyHandler);
58         Proxy.setHandler(ProxyHandler);
59         AuthedProxy.setHandler(AuthedProxyHandler);
60 
61         // TLS setup:
62         try {
63             File keystoreFile = ParseTest.getFile("/local-cert/server.pfx");
keystoreFile.toString()64             if (!keystoreFile.exists()) throw new FileNotFoundException(keystoreFile.toString());
addHttpsConnector(keystoreFile, Jetty)65             addHttpsConnector(keystoreFile, Jetty);
66             setupDefaultTrust(keystoreFile);
67         } catch (Exception e) {
68             throw new IllegalStateException(e);
69         }
70     }
71 
TestServer()72     private TestServer() {
73     }
74 
start()75     public static void start() {
76         synchronized (Jetty) {
77             if (Jetty.isStarted()) return;
78 
79             try {
80                 Jetty.start();
81                 JettyHandler.addFilterWithMapping(new FilterHolder(new AuthFilter(false, false)), "/*", FilterMapping.ALL);
82                 Connector[] jcons = Jetty.getConnectors();
83                 Port = ((ServerConnector) jcons[0]).getLocalPort();
84                 TlsPort = ((ServerConnector) jcons[1]).getLocalPort();
85 
86                 ProxyHandler.setHandler(ProxyServlet.createHandler(false)); // includes proxy, CONNECT proxy, and Auth filters
87                 Proxy.start();
88                 ProxySettings.port = ((ServerConnector) Proxy.getConnectors()[0]).getLocalPort();
89 
90                 AuthedProxyHandler.setHandler(ProxyServlet.createHandler(true));
91                 AuthedProxy.start();
92                 ProxySettings.authedPort = ((ServerConnector) AuthedProxy.getConnectors()[0]).getLocalPort();
93             } catch (Exception e) {
94                 throw new IllegalStateException(e);
95             }
96         }
97     }
98 
99     /**
100      Close any current connections to the authed proxy. Tunneled connections only authenticate in their first
101      CONNECT, and may be kept alive and reused. So when we want to test unauthed - authed flows, we need to disconnect
102      them first.
103      */
closeAuthedProxyConnections()104     static int closeAuthedProxyConnections() {
105         ServerConnector connector = (ServerConnector) AuthedProxy.getConnectors()[0];
106         AtomicInteger count = new AtomicInteger();
107         connector.getConnectedEndPoints().forEach(endPoint -> {
108             endPoint.close();
109             count.getAndIncrement();
110         });
111         return count.get();
112     }
113 
map(Class<? extends BaseServlet> servletClass)114     public static ServletUrls map(Class<? extends BaseServlet> servletClass) {
115         synchronized (Jetty) {
116             if (!Jetty.isStarted())
117                 start(); // if running out of the test cases
118 
119             String path = "/" + servletClass.getSimpleName();
120             JettyHandler.addServletWithMapping(servletClass, path + "/*");
121             String url = "http://" + Localhost + ":" + Port + path;
122             String tlsUrl = "https://" + Localhost + ":" + TlsPort + path;
123 
124             return new ServletUrls(url, tlsUrl);
125         }
126     }
127 
128     public static class ServletUrls {
129         public final String url;
130         public final String tlsUrl;
131 
ServletUrls(String url, String tlsUrl)132         public ServletUrls(String url, String tlsUrl) {
133             this.url = url;
134             this.tlsUrl = tlsUrl;
135         }
136     }
137 
proxySettings()138     public static ProxySettings proxySettings() {
139         synchronized (Jetty) {
140             if (!Jetty.isStarted())
141                 start();
142 
143             return ProxySettings;
144         }
145     }
146 
147     //public static String proxy
148     public static class ProxySettings {
149         final String hostname = Localhost;
150         int port;
151         int authedPort;
152     }
153 
addHttpsConnector(File keystoreFile, Server server)154     private static void addHttpsConnector(File keystoreFile, Server server) {
155         // Cribbed from https://github.com/jetty/jetty.project/blob/jetty-9.4.x/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java
156         SslContextFactory sslContextFactory = new SslContextFactory.Server();
157         String path = keystoreFile.getAbsolutePath();
158         sslContextFactory.setKeyStorePath(path);
159         sslContextFactory.setKeyStorePassword(KeystorePassword);
160         sslContextFactory.setKeyManagerPassword(KeystorePassword);
161         sslContextFactory.setTrustStorePath(path);
162         sslContextFactory.setTrustStorePassword(KeystorePassword);
163 
164         HttpConfiguration httpConfig = new HttpConfiguration();
165         httpConfig.setSecureScheme("https");
166         HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig);
167         httpsConfig.addCustomizer(new SecureRequestCustomizer());
168 
169         ServerConnector sslConnector = new ServerConnector(
170             server,
171             new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
172             new HttpConnectionFactory(httpsConfig));
173         server.addConnector(sslConnector);
174     }
175 
setupDefaultTrust(File keystoreFile)176     private static void setupDefaultTrust(File keystoreFile) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, KeyManagementException {
177         // Configure HttpsUrlConnection (jsoup) to trust (only) this cert
178         KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
179         trustStore.load(Files.newInputStream(keystoreFile.toPath()), KeystorePassword.toCharArray());
180         TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
181         trustManagerFactory.init(trustStore);
182         TrustManager[] managers = trustManagerFactory.getTrustManagers();
183         SSLContext tls = SSLContext.getInstance("TLS");
184         tls.init(null, managers, null);
185         SSLSocketFactory socketFactory = tls.getSocketFactory();
186         HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory);
187     }
188 }
189