1 43 44 package org.apache.commons.httpclient.contrib.ssl; 45 46 import java.io.IOException ; 47 import java.net.InetAddress ; 48 import java.net.InetSocketAddress ; 49 import java.net.Socket ; 50 import java.net.SocketAddress ; 51 import java.net.UnknownHostException ; 52 53 import javax.net.SocketFactory; 54 import javax.net.ssl.SSLPeerUnverifiedException; 55 import javax.net.ssl.SSLSession; 56 import javax.net.ssl.SSLSocket; 57 import javax.net.ssl.SSLSocketFactory; 58 import javax.security.cert.X509Certificate; 59 60 import org.apache.commons.httpclient.ConnectTimeoutException; 61 import org.apache.commons.httpclient.params.HttpConnectionParams; 62 import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; 63 import org.apache.commons.logging.Log; 64 import org.apache.commons.logging.LogFactory; 65 66 82 public class StrictSSLProtocolSocketFactory 83 implements SecureProtocolSocketFactory { 84 85 86 private static final Log LOG = LogFactory.getLog(StrictSSLProtocolSocketFactory.class); 87 88 89 private boolean verifyHostname = true; 90 91 92 113 public StrictSSLProtocolSocketFactory(boolean verifyHostname) { 114 super(); 115 this.verifyHostname = verifyHostname; 116 } 117 118 122 public StrictSSLProtocolSocketFactory() { 123 super(); 124 } 125 126 137 public void setHostnameVerification(boolean verifyHostname) { 138 this.verifyHostname = verifyHostname; 139 } 140 141 148 public boolean getHostnameVerification() { 149 return verifyHostname; 150 } 151 152 153 156 public Socket createSocket(String host, int port, 157 InetAddress clientHost, int clientPort) 158 throws IOException , UnknownHostException { 159 SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); 160 SSLSocket sslSocket = (SSLSocket) sf.createSocket(host, port, 161 clientHost, 162 clientPort); 163 verifyHostname(sslSocket); 164 165 return sslSocket; 166 } 167 168 191 public Socket createSocket( 192 final String host, 193 final int port, 194 final InetAddress localAddress, 195 final int localPort, 196 final HttpConnectionParams params 197 ) throws IOException , UnknownHostException , ConnectTimeoutException { 198 if (params == null) { 199 throw new IllegalArgumentException ("Parameters may not be null"); 200 } 201 int timeout = params.getConnectionTimeout(); 202 Socket socket = null; 203 204 SocketFactory socketfactory = SSLSocketFactory.getDefault(); 205 if (timeout == 0) { 206 socket = socketfactory.createSocket(host, port, localAddress, localPort); 207 } else { 208 socket = socketfactory.createSocket(); 209 SocketAddress localaddr = new InetSocketAddress (localAddress, localPort); 210 SocketAddress remoteaddr = new InetSocketAddress (host, port); 211 socket.bind(localaddr); 212 socket.connect(remoteaddr, timeout); 213 } 214 verifyHostname((SSLSocket)socket); 215 return socket; 216 } 217 218 221 public Socket createSocket(String host, int port) 222 throws IOException , UnknownHostException { 223 SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); 224 SSLSocket sslSocket = (SSLSocket) sf.createSocket(host, port); 225 verifyHostname(sslSocket); 226 227 return sslSocket; 228 } 229 230 233 public Socket createSocket(Socket socket, String host, int port, 234 boolean autoClose) 235 throws IOException , UnknownHostException { 236 SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); 237 SSLSocket sslSocket = (SSLSocket) sf.createSocket(socket, host, 238 port, autoClose); 239 verifyHostname(sslSocket); 240 241 return sslSocket; 242 } 243 244 245 256 private void verifyHostname(SSLSocket socket) 257 throws SSLPeerUnverifiedException, UnknownHostException { 258 if (! verifyHostname) 259 return; 260 261 SSLSession session = socket.getSession(); 262 String hostname = session.getPeerHost(); 263 try { 264 InetAddress addr = InetAddress.getByName(hostname); 265 } catch (UnknownHostException uhe) { 266 throw new UnknownHostException ("Could not resolve SSL sessions " 267 + "server hostname: " + hostname); 268 } 269 270 X509Certificate[] certs = session.getPeerCertificateChain(); 271 if (certs == null || certs.length == 0) 272 throw new SSLPeerUnverifiedException("No server certificates found!"); 273 274 String dn = certs[0].getSubjectDN().getName(); 276 277 if (LOG.isDebugEnabled()) { 280 LOG.debug("Server certificate chain:"); 281 for (int i = 0; i < certs.length; i++) { 282 LOG.debug("X509Certificate[" + i + "]=" + certs[i]); 283 } 284 } 285 String cn = getCN(dn); 287 if (hostname.equalsIgnoreCase(cn)) { 288 if (LOG.isDebugEnabled()) { 289 LOG.debug("Target hostname valid: " + cn); 290 } 291 } else { 292 throw new SSLPeerUnverifiedException( 293 "HTTPS hostname invalid: expected '" + hostname + "', received '" + cn + "'"); 294 } 295 } 296 297 298 307 private String getCN(String dn) { 308 int i = 0; 309 i = dn.indexOf("CN="); 310 if (i == -1) { 311 return null; 312 } 313 dn = dn.substring(i + 3); 315 char[] dncs = dn.toCharArray(); 317 for (i = 0; i < dncs.length; i++) { 318 if (dncs[i] == ',' && i > 0 && dncs[i - 1] != '\\') { 319 break; 320 } 321 } 322 return dn.substring(0, i); 323 } 324 325 public boolean equals(Object obj) { 326 if ((obj != null) && obj.getClass().equals(StrictSSLProtocolSocketFactory.class)) { 327 return ((StrictSSLProtocolSocketFactory) obj).getHostnameVerification() 328 == this.verifyHostname; 329 } else { 330 return false; 331 } 332 } 333 334 public int hashCode() { 335 return StrictSSLProtocolSocketFactory.class.hashCode(); 336 } 337 338 } | Popular Tags |