1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.http.nio.conn.ssl;
29
30 import java.io.IOException;
31 import java.security.cert.Certificate;
32 import java.security.cert.X509Certificate;
33
34 import javax.net.ssl.HostnameVerifier;
35 import javax.net.ssl.SSLContext;
36 import javax.net.ssl.SSLEngine;
37 import javax.net.ssl.SSLException;
38 import javax.net.ssl.SSLPeerUnverifiedException;
39 import javax.net.ssl.SSLSession;
40 import javax.security.auth.x500.X500Principal;
41
42 import org.apache.http.HttpHost;
43 import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
44 import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
45 import org.apache.http.conn.ssl.DefaultHostnameVerifier;
46 import org.apache.http.conn.ssl.StrictHostnameVerifier;
47 import org.apache.http.conn.ssl.X509HostnameVerifier;
48 import org.apache.http.conn.util.PublicSuffixMatcherLoader;
49 import org.apache.http.nio.conn.SchemeIOSessionStrategy;
50 import org.apache.http.nio.reactor.IOSession;
51 import org.apache.http.nio.reactor.ssl.SSLIOSession;
52 import org.apache.http.nio.reactor.ssl.SSLMode;
53 import org.apache.http.nio.reactor.ssl.SSLSetupHandler;
54 import org.apache.http.ssl.SSLContexts;
55 import org.apache.http.util.Args;
56 import org.apache.http.util.Asserts;
57 import org.apache.http.util.TextUtils;
58
59
60
61
62
63
64 public class SSLIOSessionStrategy implements SchemeIOSessionStrategy {
65
66
67
68
69 @Deprecated
70 public static final X509HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER =
71 new AllowAllHostnameVerifier();
72
73
74
75
76 @Deprecated
77 public static final X509HostnameVerifier BROWSER_COMPATIBLE_HOSTNAME_VERIFIER =
78 new BrowserCompatHostnameVerifier();
79
80
81
82
83 @Deprecated
84 public static final X509HostnameVerifier STRICT_HOSTNAME_VERIFIER =
85 new StrictHostnameVerifier();
86
87 private static String[] split(final String s) {
88 if (TextUtils.isBlank(s)) {
89 return null;
90 }
91 return s.split(" *, *");
92 }
93
94
95
96
97 public static HostnameVerifier getDefaultHostnameVerifier() {
98 return new DefaultHostnameVerifier(PublicSuffixMatcherLoader.getDefault());
99 }
100
101 public static SSLIOSessionStrategy getDefaultStrategy() {
102 return new SSLIOSessionStrategy(
103 SSLContexts.createDefault(),
104 getDefaultHostnameVerifier());
105 }
106
107 public static SSLIOSessionStrategy getSystemDefaultStrategy() {
108 return new SSLIOSessionStrategy(
109 SSLContexts.createSystemDefault(),
110 split(System.getProperty("https.protocols")),
111 split(System.getProperty("https.cipherSuites")),
112 getDefaultHostnameVerifier());
113 }
114
115 private final SSLContext sslContext;
116 private final String[] supportedProtocols;
117 private final String[] supportedCipherSuites;
118 private final HostnameVerifier hostnameVerifier;
119
120
121
122
123
124 @Deprecated
125 public SSLIOSessionStrategy(
126 final SSLContext sslContext,
127 final String[] supportedProtocols,
128 final String[] supportedCipherSuites,
129 final X509HostnameVerifier hostnameVerifier) {
130 this(sslContext, supportedProtocols, supportedCipherSuites, (HostnameVerifier) hostnameVerifier);
131 }
132
133
134
135
136 @Deprecated
137 public SSLIOSessionStrategy(
138 final SSLContext sslcontext,
139 final X509HostnameVerifier hostnameVerifier) {
140 this(sslcontext, null, null, (HostnameVerifier) hostnameVerifier);
141 }
142
143
144
145
146 public SSLIOSessionStrategy(
147 final SSLContext sslContext,
148 final String[] supportedProtocols,
149 final String[] supportedCipherSuites,
150 final HostnameVerifier hostnameVerifier) {
151 super();
152 this.sslContext = Args.notNull(sslContext, "SSL context");
153 this.supportedProtocols = supportedProtocols;
154 this.supportedCipherSuites = supportedCipherSuites;
155 this.hostnameVerifier = hostnameVerifier != null ? hostnameVerifier : getDefaultHostnameVerifier();
156 }
157
158
159
160
161 public SSLIOSessionStrategy(
162 final SSLContext sslcontext,
163 final HostnameVerifier hostnameVerifier) {
164 this(sslcontext, null, null, hostnameVerifier);
165 }
166
167 public SSLIOSessionStrategy(final SSLContext sslcontext) {
168 this(sslcontext, null, null, getDefaultHostnameVerifier());
169 }
170
171 @Override
172 public SSLIOSession upgrade(final HttpHost host, final IOSession ioSession) throws IOException {
173 Asserts.check(!(ioSession instanceof SSLIOSession), "I/O session is already upgraded to TLS/SSL");
174 final SSLIOSession sslioSession = new SSLIOSession(
175 ioSession,
176 SSLMode.CLIENT,
177 host,
178 this.sslContext,
179 new SSLSetupHandler() {
180
181 @Override
182 public void initalize(
183 final SSLEngine sslengine) throws SSLException {
184 if (supportedProtocols != null) {
185 sslengine.setEnabledProtocols(supportedProtocols);
186 }
187 if (supportedCipherSuites != null) {
188 sslengine.setEnabledCipherSuites(supportedCipherSuites);
189 }
190 initializeEngine(sslengine);
191 }
192
193 @Override
194 public void verify(
195 final IOSession ioSession,
196 final SSLSession sslsession) throws SSLException {
197 verifySession(host, ioSession, sslsession);
198 }
199
200 });
201 ioSession.setAttribute(SSLIOSession.SESSION_KEY, sslioSession);
202 sslioSession.initialize();
203 return sslioSession;
204 }
205
206 protected void initializeEngine(final SSLEngine engine) {
207 }
208
209 protected void verifySession(
210 final HttpHost host,
211 final IOSession ioSession,
212 final SSLSession sslsession) throws SSLException {
213 if (!this.hostnameVerifier.verify(host.getHostName(), sslsession)) {
214 final Certificate[] certs = sslsession.getPeerCertificates();
215 final X509Certificate x509 = (X509Certificate) certs[0];
216 final X500Principal x500Principal = x509.getSubjectX500Principal();
217 throw new SSLPeerUnverifiedException("Host name '" + host.getHostName() + "' does not match " +
218 "the certificate subject provided by the peer (" + x500Principal.toString() + ")");
219 }
220 }
221
222 @Override
223 public boolean isLayeringRequired() {
224 return true;
225 }
226
227 }