1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.handler.ssl;
17
18 import io.netty5.util.internal.EmptyArrays;
19 import io.netty5.util.internal.PlatformDependent;
20 import io.netty5.util.internal.logging.InternalLogger;
21 import io.netty5.util.internal.logging.InternalLoggerFactory;
22
23 import javax.net.ssl.SSLContext;
24 import javax.net.ssl.TrustManager;
25 import javax.net.ssl.X509ExtendedTrustManager;
26 import javax.net.ssl.X509TrustManager;
27 import java.lang.reflect.Field;
28 import java.security.AccessController;
29 import java.security.KeyManagementException;
30 import java.security.NoSuchAlgorithmException;
31 import java.security.NoSuchProviderException;
32 import java.security.PrivilegedAction;
33 import java.security.cert.CertificateException;
34 import java.security.cert.X509Certificate;
35
36
37
38
39
40
41
42
43 final class OpenSslX509TrustManagerWrapper {
44 private static final InternalLogger LOGGER = InternalLoggerFactory
45 .getInstance(OpenSslX509TrustManagerWrapper.class);
46 private static final TrustManagerWrapper WRAPPER;
47
48 static {
49
50 TrustManagerWrapper wrapper = manager -> manager;
51
52 Throwable cause = null;
53 Throwable unsafeCause = PlatformDependent.getUnsafeUnavailabilityCause();
54 if (unsafeCause == null) {
55 SSLContext context;
56 try {
57 context = newSSLContext();
58
59
60
61
62
63
64
65 context.init(null, new TrustManager[] {
66 new X509TrustManager() {
67 @Override
68 public void checkClientTrusted(X509Certificate[] x509Certificates, String s)
69 throws CertificateException {
70 throw new CertificateException();
71 }
72
73 @Override
74 public void checkServerTrusted(X509Certificate[] x509Certificates, String s)
75 throws CertificateException {
76 throw new CertificateException();
77 }
78
79 @Override
80 public X509Certificate[] getAcceptedIssuers() {
81 return EmptyArrays.EMPTY_X509_CERTIFICATES;
82 }
83 }
84 }, null);
85 } catch (Throwable error) {
86 context = null;
87 cause = error;
88 }
89 if (cause != null) {
90 LOGGER.debug("Unable to access wrapped TrustManager", cause);
91 } else {
92 final SSLContext finalContext = context;
93 Object maybeWrapper = AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
94 try {
95 Field contextSpiField = SSLContext.class.getDeclaredField("contextSpi");
96 final long spiOffset = PlatformDependent.objectFieldOffset(contextSpiField);
97 Object spi = PlatformDependent.getObject(finalContext, spiOffset);
98 if (spi != null) {
99 Class<?> clazz = spi.getClass();
100
101
102
103 do {
104 try {
105 Field trustManagerField = clazz.getDeclaredField("trustManager");
106 final long tmOffset = PlatformDependent.objectFieldOffset(trustManagerField);
107 Object trustManager = PlatformDependent.getObject(spi, tmOffset);
108 if (trustManager instanceof X509ExtendedTrustManager) {
109 return new UnsafeTrustManagerWrapper(spiOffset, tmOffset);
110 }
111 } catch (NoSuchFieldException ignore) {
112
113 }
114 clazz = clazz.getSuperclass();
115 } while (clazz != null);
116 }
117 throw new NoSuchFieldException();
118 } catch (NoSuchFieldException | SecurityException e) {
119 return e;
120 }
121 });
122 if (maybeWrapper instanceof Throwable) {
123 LOGGER.debug("Unable to access wrapped TrustManager", (Throwable) maybeWrapper);
124 } else {
125 wrapper = (TrustManagerWrapper) maybeWrapper;
126 }
127 }
128 } else {
129 LOGGER.debug("Unable to access wrapped TrustManager", cause);
130 }
131 WRAPPER = wrapper;
132 }
133
134 private OpenSslX509TrustManagerWrapper() { }
135
136 static X509TrustManager wrapIfNeeded(X509TrustManager trustManager) {
137 return WRAPPER.wrapIfNeeded(trustManager);
138 }
139
140 private interface TrustManagerWrapper {
141 X509TrustManager wrapIfNeeded(X509TrustManager manager);
142 }
143
144 private static SSLContext newSSLContext() throws NoSuchAlgorithmException, NoSuchProviderException {
145
146
147 return SSLContext.getInstance("TLS", "SunJSSE");
148 }
149
150 private static final class UnsafeTrustManagerWrapper implements TrustManagerWrapper {
151 private final long spiOffset;
152 private final long tmOffset;
153
154 UnsafeTrustManagerWrapper(long spiOffset, long tmOffset) {
155 this.spiOffset = spiOffset;
156 this.tmOffset = tmOffset;
157 }
158
159 @Override
160 public X509TrustManager wrapIfNeeded(X509TrustManager manager) {
161 if (!(manager instanceof X509ExtendedTrustManager)) {
162 try {
163 SSLContext ctx = newSSLContext();
164 ctx.init(null, new TrustManager[] { manager }, null);
165 Object spi = PlatformDependent.getObject(ctx, spiOffset);
166 if (spi != null) {
167 Object tm = PlatformDependent.getObject(spi, tmOffset);
168 if (tm instanceof X509ExtendedTrustManager) {
169 return (X509TrustManager) tm;
170 }
171 }
172 } catch (NoSuchAlgorithmException | KeyManagementException | NoSuchProviderException e) {
173
174
175 PlatformDependent.throwException(e);
176 }
177 }
178 return manager;
179 }
180 }
181 }