001: /*
002: * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/contrib/org/apache/commons/httpclient/contrib/ssl/EasySSLProtocolSocketFactory.java,v 1.7 2004/06/11 19:26:27 olegk Exp $
003: * $Revision$
004: * $Date$
005: *
006: * ====================================================================
007: *
008: * Copyright 2002-2004 The Apache Software Foundation
009: *
010: * Licensed under the Apache License, Version 2.0 (the "License");
011: * you may not use this file except in compliance with the License.
012: * You may obtain a copy of the License at
013: *
014: * http://www.apache.org/licenses/LICENSE-2.0
015: *
016: * Unless required by applicable law or agreed to in writing, software
017: * distributed under the License is distributed on an "AS IS" BASIS,
018: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
019: * See the License for the specific language governing permissions and
020: * limitations under the License.
021: * ====================================================================
022: *
023: * This software consists of voluntary contributions made by many
024: * individuals on behalf of the Apache Software Foundation. For more
025: * information on the Apache Software Foundation, please see
026: * <http://www.apache.org/>.
027: *
028: */
029:
030: package org.apache.commons.httpclient.contrib.ssl;
031:
032: import java.io.IOException;
033: import java.net.InetAddress;
034: import java.net.InetSocketAddress;
035: import java.net.Socket;
036: import java.net.SocketAddress;
037: import java.net.UnknownHostException;
038:
039: import org.apache.commons.httpclient.ConnectTimeoutException;
040: import org.apache.commons.httpclient.HttpClientError;
041: import org.apache.commons.httpclient.params.HttpConnectionParams;
042: import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
043: import org.apache.commons.logging.Log;
044: import org.apache.commons.logging.LogFactory;
045:
046: import javax.net.SocketFactory;
047: import javax.net.ssl.SSLContext;
048: import javax.net.ssl.TrustManager;
049:
050: /**
051: * <p>
052: * EasySSLProtocolSocketFactory can be used to creats SSL {@link Socket}s
053: * that accept self-signed certificates.
054: * </p>
055: * <p>
056: * This socket factory SHOULD NOT be used for productive systems
057: * due to security reasons, unless it is a concious decision and
058: * you are perfectly aware of security implications of accepting
059: * self-signed certificates
060: * </p>
061: *
062: * <p>
063: * Example of using custom protocol socket factory for a specific host:
064: * <pre>
065: * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
066: *
067: * HttpClient client = new HttpClient();
068: * client.getHostConfiguration().setHost("localhost", 443, easyhttps);
069: * // use relative url only
070: * GetMethod httpget = new GetMethod("/");
071: * client.executeMethod(httpget);
072: * </pre>
073: * </p>
074: * <p>
075: * Example of using custom protocol socket factory per default instead of the standard one:
076: * <pre>
077: * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
078: * Protocol.registerProtocol("https", easyhttps);
079: *
080: * HttpClient client = new HttpClient();
081: * GetMethod httpget = new GetMethod("https://localhost/");
082: * client.executeMethod(httpget);
083: * </pre>
084: * </p>
085: *
086: * @author <a href="mailto:oleg -at- ural.ru">Oleg Kalnichevski</a>
087: *
088: * <p>
089: * DISCLAIMER: HttpClient developers DO NOT actively support this component.
090: * The component is provided as a reference material, which may be inappropriate
091: * for use without additional customization.
092: * </p>
093: */
094:
095: public class EasySSLProtocolSocketFactory implements
096: SecureProtocolSocketFactory {
097:
098: /** Log object for this class. */
099: private static final Log LOG = LogFactory
100: .getLog(EasySSLProtocolSocketFactory.class);
101:
102: private SSLContext sslcontext = null;
103:
104: /**
105: * Constructor for EasySSLProtocolSocketFactory.
106: */
107: public EasySSLProtocolSocketFactory() {
108: super ();
109: }
110:
111: private static SSLContext createEasySSLContext() {
112: try {
113: SSLContext context = SSLContext.getInstance("SSL");
114: context
115: .init(
116: null,
117: new TrustManager[] { new EasyX509TrustManager(
118: null) }, null);
119: return context;
120: } catch (Exception e) {
121: LOG.error(e.getMessage(), e);
122: throw new HttpClientError(e.toString());
123: }
124: }
125:
126: private SSLContext getSSLContext() {
127: if (this .sslcontext == null) {
128: this .sslcontext = createEasySSLContext();
129: }
130: return this .sslcontext;
131: }
132:
133: /**
134: * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int)
135: */
136: public Socket createSocket(String host, int port,
137: InetAddress clientHost, int clientPort) throws IOException,
138: UnknownHostException {
139:
140: return getSSLContext().getSocketFactory().createSocket(host,
141: port, clientHost, clientPort);
142: }
143:
144: /**
145: * Attempts to get a new socket connection to the given host within the given time limit.
146: * <p>
147: * To circumvent the limitations of older JREs that do not support connect timeout a
148: * controller thread is executed. The controller thread attempts to create a new socket
149: * within the given limit of time. If socket constructor does not return until the
150: * timeout expires, the controller terminates and throws an {@link ConnectTimeoutException}
151: * </p>
152: *
153: * @param host the host name/IP
154: * @param port the port on the host
155: * @param clientHost the local host name/IP to bind the socket to
156: * @param clientPort the port on the local machine
157: * @param params {@link HttpConnectionParams Http connection parameters}
158: *
159: * @return Socket a new socket
160: *
161: * @throws IOException if an I/O error occurs while creating the socket
162: * @throws UnknownHostException if the IP address of the host cannot be
163: * determined
164: */
165: public Socket createSocket(final String host, final int port,
166: final InetAddress localAddress, final int localPort,
167: final HttpConnectionParams params) throws IOException,
168: UnknownHostException, ConnectTimeoutException {
169: if (params == null) {
170: throw new IllegalArgumentException(
171: "Parameters may not be null");
172: }
173: int timeout = params.getConnectionTimeout();
174: SocketFactory socketfactory = getSSLContext()
175: .getSocketFactory();
176: if (timeout == 0) {
177: return socketfactory.createSocket(host, port, localAddress,
178: localPort);
179: } else {
180: Socket socket = socketfactory.createSocket();
181: SocketAddress localaddr = new InetSocketAddress(
182: localAddress, localPort);
183: SocketAddress remoteaddr = new InetSocketAddress(host, port);
184: socket.bind(localaddr);
185: socket.connect(remoteaddr, timeout);
186: return socket;
187: }
188: }
189:
190: /**
191: * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int)
192: */
193: public Socket createSocket(String host, int port)
194: throws IOException, UnknownHostException {
195: return getSSLContext().getSocketFactory().createSocket(host,
196: port);
197: }
198:
199: /**
200: * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean)
201: */
202: public Socket createSocket(Socket socket, String host, int port,
203: boolean autoClose) throws IOException, UnknownHostException {
204: return getSSLContext().getSocketFactory().createSocket(socket,
205: host, port, autoClose);
206: }
207:
208: public boolean equals(Object obj) {
209: return ((obj != null) && obj.getClass().equals(
210: EasySSLProtocolSocketFactory.class));
211: }
212:
213: public int hashCode() {
214: return EasySSLProtocolSocketFactory.class.hashCode();
215: }
216:
217: }
|