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