|
20 | 20 | import com.dajudge.proxybase.certs.Filesystem; |
21 | 21 | import com.dajudge.proxybase.certs.KeyStoreManager; |
22 | 22 | import com.dajudge.proxybase.config.DownstreamSslConfig; |
| 23 | +import com.dajudge.proxybase.config.Endpoint; |
| 24 | +import io.netty.channel.Channel; |
23 | 25 | import io.netty.channel.ChannelHandler; |
24 | | -import io.netty.handler.ssl.SslHandler; |
| 26 | +import io.netty.channel.socket.SocketChannel; |
| 27 | +import io.netty.handler.ssl.SslContext; |
| 28 | +import io.netty.handler.ssl.SslContextBuilder; |
25 | 29 |
|
26 | | -import javax.net.ssl.SSLContext; |
27 | | -import javax.net.ssl.SSLEngine; |
28 | | -import javax.net.ssl.X509TrustManager; |
| 30 | +import javax.net.ssl.*; |
29 | 31 | import java.security.KeyManagementException; |
30 | 32 | import java.security.NoSuchAlgorithmException; |
31 | 33 | import java.util.Optional; |
| 34 | +import java.util.function.Function; |
32 | 35 | import java.util.function.Supplier; |
33 | 36 |
|
34 | 37 | import static com.dajudge.proxybase.HostnameCheck.NULL_VERIFIER; |
35 | | -import static com.dajudge.proxybase.SslUtils.createKeyManagers; |
36 | | -import static com.dajudge.proxybase.SslUtils.createTrustManagers; |
| 38 | +import static com.dajudge.proxybase.SslUtils.*; |
37 | 39 | import static com.dajudge.proxybase.certs.ReloadingKeyStoreManager.createReloader; |
38 | 40 |
|
39 | 41 | public class DownstreamSslHandlerFactory { |
40 | | - public static ChannelHandler createDownstreamSslHandler( |
| 42 | + public static Function<Channel, ChannelHandler> createDownstreamSslHandler( |
41 | 43 | final DownstreamSslConfig config, |
42 | | - final String downstreamHostname, |
| 44 | + final Endpoint downstreamEndpoint, |
43 | 45 | final Supplier<Long> clock, |
44 | 46 | final Filesystem filesystem |
45 | | - ) { |
| 47 | + ) { |
46 | 48 | final HostnameCheck hostnameCheck = config.isHostnameVerificationEnabled() |
47 | | - ? new HttpClientHostnameCheck(downstreamHostname) |
| 49 | + ? new HttpClientHostnameCheck(downstreamEndpoint.getHost()) |
48 | 50 | : NULL_VERIFIER; |
49 | 51 | return createDownstreamSslHandler( |
50 | 52 | hostnameCheck, |
51 | 53 | createReloader(config.getTrustStore(), clock, filesystem), |
52 | | - config.getKeyStore().map(it -> createReloader(it, clock, filesystem)) |
| 54 | + config.getKeyStore().map(it -> createReloader(it, clock, filesystem)), |
| 55 | + Optional.of(downstreamEndpoint) |
53 | 56 | ); |
54 | 57 | } |
55 | 58 |
|
56 | | - public static ChannelHandler createDownstreamSslHandler( |
| 59 | + public static Function<Channel, ChannelHandler> createDownstreamSslHandler( |
57 | 60 | final HostnameCheck hostnameCheck, |
58 | 61 | final KeyStoreManager trustStoreManager, |
59 | | - final Optional<KeyStoreManager> keyStoreManager |
| 62 | + final Optional<KeyStoreManager> keyStoreManager, |
| 63 | + final Optional<Endpoint> peerEndpoint |
60 | 64 | ) { |
61 | 65 | try { |
62 | 66 | final SSLContext clientContext = SSLContext.getInstance("TLS"); |
| 67 | + final HostCheckingTrustManager trustManager = new HostCheckingTrustManager( |
| 68 | + createTrustManagers(trustStoreManager), |
| 69 | + hostnameCheck |
| 70 | + ); |
63 | 71 | final X509TrustManager[] trustManagers = { |
64 | | - new HostCheckingTrustManager(createTrustManagers(trustStoreManager), hostnameCheck) |
| 72 | + trustManager |
65 | 73 | }; |
66 | | - clientContext.init(createKeyManagers(keyStoreManager), trustManagers, null); |
67 | | - final SSLEngine engine = clientContext.createSSLEngine(); |
| 74 | + final X509KeyManager[] keyManagers = createKeyManagers(keyStoreManager); |
| 75 | + clientContext.init(keyManagers, trustManagers, null); |
| 76 | + final SSLEngine engine = peerEndpoint |
| 77 | + .map(it -> clientContext.createSSLEngine(it.getHost(), it.getPort())) |
| 78 | + .orElse(clientContext.createSSLEngine()); |
68 | 79 | engine.setUseClientMode(true); |
69 | | - return new SslHandler(engine); |
70 | | - } catch (final NoSuchAlgorithmException | KeyManagementException e) { |
| 80 | + final SslContext context = SslContextBuilder.forClient() |
| 81 | + .keyManager(createKeyManagerFactory(keyStoreManager)) |
| 82 | + .trustManager(trustManager) |
| 83 | + .build(); |
| 84 | + if (peerEndpoint.isPresent()) { |
| 85 | + return ch -> { |
| 86 | + final Endpoint endpoint = peerEndpoint.get(); |
| 87 | + return context.newHandler(ch.alloc(), endpoint.getHost(), endpoint.getPort()); |
| 88 | + }; |
| 89 | + } else { |
| 90 | + return ch -> context.newHandler(ch.alloc()); |
| 91 | + } |
| 92 | + } catch (final NoSuchAlgorithmException | KeyManagementException | SSLException e) { |
71 | 93 | throw new RuntimeException("Failed to initialize downstream SSL handler", e); |
72 | 94 | } |
73 | 95 | } |
|
0 commit comments