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 @Deprecated
67 public static final X509HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER =
68 new AllowAllHostnameVerifier();
69
70 @Deprecated
71 public static final X509HostnameVerifier BROWSER_COMPATIBLE_HOSTNAME_VERIFIER =
72 new BrowserCompatHostnameVerifier();
73
74 @Deprecated
75 public static final X509HostnameVerifier STRICT_HOSTNAME_VERIFIER =
76 new StrictHostnameVerifier();
77
78 private static String[] split(final String s) {
79 if (TextUtils.isBlank(s)) {
80 return null;
81 }
82 return s.split(" *, *");
83 }
84
85
86
87
88 public static HostnameVerifier getDefaultHostnameVerifier() {
89 return new DefaultHostnameVerifier(PublicSuffixMatcherLoader.getDefault());
90 }
91
92 public static SSLIOSessionStrategy getDefaultStrategy() {
93 return new SSLIOSessionStrategy(
94 SSLContexts.createDefault(),
95 getDefaultHostnameVerifier());
96 }
97
98 public static SSLIOSessionStrategy getSystemDefaultStrategy() {
99 return new SSLIOSessionStrategy(
100 SSLContexts.createSystemDefault(),
101 split(System.getProperty("https.protocols")),
102 split(System.getProperty("https.cipherSuites")),
103 getDefaultHostnameVerifier());
104 }
105
106 private final SSLContext sslContext;
107 private final String[] supportedProtocols;
108 private final String[] supportedCipherSuites;
109 private final HostnameVerifier hostnameVerifier;
110
111
112
113
114
115 @Deprecated
116 public SSLIOSessionStrategy(
117 final SSLContext sslContext,
118 final String[] supportedProtocols,
119 final String[] supportedCipherSuites,
120 final X509HostnameVerifier hostnameVerifier) {
121 this(sslContext, supportedProtocols, supportedCipherSuites, (HostnameVerifier) hostnameVerifier);
122 }
123
124
125
126
127 @Deprecated
128 public SSLIOSessionStrategy(
129 final SSLContext sslcontext,
130 final X509HostnameVerifier hostnameVerifier) {
131 this(sslcontext, null, null, (HostnameVerifier) hostnameVerifier);
132 }
133
134
135
136
137 public SSLIOSessionStrategy(
138 final SSLContext sslContext,
139 final String[] supportedProtocols,
140 final String[] supportedCipherSuites,
141 final HostnameVerifier hostnameVerifier) {
142 super();
143 this.sslContext = Args.notNull(sslContext, "SSL context");
144 this.supportedProtocols = supportedProtocols;
145 this.supportedCipherSuites = supportedCipherSuites;
146 this.hostnameVerifier = hostnameVerifier != null ? hostnameVerifier : getDefaultHostnameVerifier();
147 }
148
149
150
151
152 public SSLIOSessionStrategy(
153 final SSLContext sslcontext,
154 final HostnameVerifier hostnameVerifier) {
155 this(sslcontext, null, null, hostnameVerifier);
156 }
157
158 public SSLIOSessionStrategy(final SSLContext sslcontext) {
159 this(sslcontext, null, null, getDefaultHostnameVerifier());
160 }
161
162 @Override
163 public SSLIOSession upgrade(final HttpHost host, final IOSession iosession) throws IOException {
164 Asserts.check(!(iosession instanceof SSLIOSession), "I/O session is already upgraded to TLS/SSL");
165 final SSLIOSession ssliosession = new SSLIOSession(
166 iosession,
167 SSLMode.CLIENT,
168 host,
169 this.sslContext,
170 new SSLSetupHandler() {
171
172 @Override
173 public void initalize(
174 final SSLEngine sslengine) throws SSLException {
175 if (supportedProtocols != null) {
176 sslengine.setEnabledProtocols(supportedProtocols);
177 }
178 if (supportedCipherSuites != null) {
179 sslengine.setEnabledCipherSuites(supportedCipherSuites);
180 }
181 initializeEngine(sslengine);
182 }
183
184 @Override
185 public void verify(
186 final IOSession iosession,
187 final SSLSession sslsession) throws SSLException {
188 verifySession(host, iosession, sslsession);
189 }
190
191 });
192 iosession.setAttribute(SSLIOSession.SESSION_KEY, ssliosession);
193 ssliosession.initialize();
194 return ssliosession;
195 }
196
197 protected void initializeEngine(final SSLEngine engine) {
198 }
199
200 protected void verifySession(
201 final HttpHost host,
202 final IOSession iosession,
203 final SSLSession sslsession) throws SSLException {
204 if (!this.hostnameVerifier.verify(host.getHostName(), sslsession)) {
205 final Certificate[] certs = sslsession.getPeerCertificates();
206 final X509Certificate x509 = (X509Certificate) certs[0];
207 final X500Principal x500Principal = x509.getSubjectX500Principal();
208 throw new SSLPeerUnverifiedException("Host name '" + host.getHostName() + "' does not match " +
209 "the certificate subject provided by the peer (" + x500Principal.toString() + ")");
210 }
211 }
212
213 @Override
214 public boolean isLayeringRequired() {
215 return true;
216 }
217
218 }